Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@profiscience/knockout-contrib

Package Overview
Dependencies
Maintainers
2
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@profiscience/knockout-contrib

KnockoutJS Goodies for building wicked awesome SPAs

  • 2.2.2
  • latest
  • Source
  • npm
  • Socket score

Version published
Maintainers
2
Created
Source

@profiscience/knockout-contrib

KnockoutJS Build Status Coverage States Gitter

Metapackage containing all of the goodies from the @profiscience/knockout-contrib monorepo. Everything you need to start building SPAs with KnockoutJS. Some bits are more opinionated than others, use however much/little as makes sense for your project. Publishing everything together as a metapackage is intended to a) reduce typing and b) increase discoverability.

Installation / Usage

First, install the metapackage. This will install the latest version of each package in @profiscience/knockout-contrib.

yarn add @profiscience/knockout-contrib

Then somewhere in your app before you kick off ko.applyBindings(), add the following boilerplate code...

NOTE: Nothing will be added to the global scope, nor any Knockout registries modified simply by installing/importing this package. You must register any bindings, components, filters, or router middleware/plugins you wish to use. This allows you to use your own loading mechanism, naming schemes, etc. if you so choose, as well as keeping each package pure (exports only, no global scope modification), enabling tree-shake-ability with webpack, rollup, or the esm bundler du jor.

/**
 * Copy this to your project, and remove any bits you don't need/want.
 *
 * **Don't'** change the knockout-contrib import statement to an `import *`
 * if you remove anything, otherwise you will not be able to take advantage of
 * tree-shaking.
 */

import * as ko from 'knockout'
import 'knockout-punches'

import {
  altClickBindingHandler,
  ctrlClickBindingHandler,
  metaClickBindingHandler,
  shiftClickBindingHandler,
  draggableBindingHandler,
  jqueryBindingHandler,
  toggleBindingHandler,
  formateDateFilter,
  Route,
  Router,
  createScrollPositionMiddleware,
  childrenRoutePlugin,
  componentRoutePlugin,
  componentsRoutePlugin,
  componentInitializerRoutePlugin,
  redirectRoutePlugin,
  createtitleRoutePlugin,
  withRoutePlugin,
} from '@profiscience/knockout-contrib'

/**
 * BINDINGS
 */

ko.bindingHandlers['click.alt'] = altClickBindingHandler
ko.bindingHandlers['click.ctrl'] = ctrlClickBindingHandler
ko.bindingHandlers['click.meta'] = metaClickBindingHandler
ko.bindingHandlers['click.shift'] = shiftClickBindingHandler

ko.bindingHandlers.draggable = draggableBindingHandler

ko.bindingHandlers.jquery = jqueryBindingHandler
ko.bindingHandlers.$ = jqueryBindingHandler // alias

ko.bindingHandlers.toggle = toggleBindingHandler

/**
 * FILTERS
 */

// punches does not have type definitions...
const _ko: any = ko

// you may remove these 2 lines if you call ko.punches.enableAll() in your project
_ko.punches.textFilter.enableForBinding('text')
_ko.punches.textFilter.enableForBinding('attr')

_ko.filters['date.format'] = formatDateFilter

/**
 * ROUTING / "FRAMEWORK"
 */
Router.use(createScrollPositionMiddleware())

// NOTE: This _must_ be executed _before_ any routes are instantiated. If you're having issues,
// remember that ES imports are hoisted, so the file that registers these plugins _must_ be imported
// before are file that instatiates a route.
Route.usePlugin(
  withRoutePlugin, // should _probably_ be first (so addt'l values are available everywhere)
  redirectRoutePlugin, // should also _probably_ be towards the top of the list (to prevent unneccesary work)
  componentRoutePlugin,
  componentInitializerRoutePlugin, // **MUST** come after component plugin

  // for the rest of these, the order is irrelevant
  childrenRoutePlugin,
  componentsRoutePlugin,
  createtitleRoutePlugin(
    (titleSegments: string[]) => `My App | ${titleSegments.join(' > ')}`
  )
)

View the documentation for individual packages to see what they do / how to use them.

Using the ESNext build

This assumes you are using webpack. It is likely possible with most other modern bundlers, but that's on you to figure out. If you would like to contribute documentation, PRs are accepted.

The default build is transpiled to ES5 in order to be compatible in older browsers (*cough* IE).

However, if you only need to support modern runtimes, you can use the esnext build. This build has much less transpilation overhead and does not require any additional runtime libraries (e.g. babel-runtime). This can have a pretty decent impact on the size of your builds when used with babel-minify, and provides for a much nicer debugging experience should you find yourself digging through the stack somewhere in this library; transpiled code can be very difficult to reason about.

This library uses the proposed esnext package.json field.

Add esnext to resolve.mainFields in your webpack config to use this build. Additionally, you'll need to configure an additional rule so that this field is used transitively. See Webpack #6796.

e.g.

module.exports = {
  resolve: {
    mainFields: [
      'esnext', // es2017+esm (resolves to <package>/dist/esnext)

      // these are the default values
      'module', // es5+esm  (resolves to <package>/dist/default)
      'main', // es5+cjs  (resolves to <package>/dist/node)
    ],
  },

  module: {
    rules: [
      {
        // https://github.com/webpack/webpack/issues/6796
        test: path.resolve(__dirname, 'node_modules'),
        resolve: {
          mainFields: ['esnext', 'es2015', 'module', 'main'],
        },
      },
    ],
  },
}

TypeScript Caveats

For reasons that are mostly related to my own development comfort, TypeScript is configured to point at the source instead of built definitions. What this comes down to is allowing parallel transpilation, however there is also the very real restriction that TypeScript refuses to emit a declaration for a mixin that uses a private or protected property.

That said, using this library with TypeScript requires a few properties to be set in your tsconfig.json.

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
    "allowSyntheticDefaultImports": true,
    "lib": [
      "dom",
      "es5",
      "es2015",
      "esnext.asynciterable"
    ]
  }
}

You may omit jsx and jsxFactory if you are not using any component packages.

Keywords

FAQs

Package last updated on 09 Oct 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc