npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@profiscience/knockout-contrib

v2.2.2

Published

KnockoutJS Goodies for building wicked awesome SPAs

Downloads

179

Readme

@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.