Skip to content

Releases: mixpanel/panel

Fixes for special cases around root node in template

18 May 23:39
Compare
Choose a tag to compare
  • If Snabbdom creates a new top-level element rather than patching DOMPatcher's existing element (for instance, when a key or tag change forces the creation of a new element), update DOMPatcher's internal element reference to point to it
  • If Snabbdom recycles the existing top-level element that DOMPatcher newly created, it won't fire the insert hook since it didn't insert any new element into the DOM, so we run the hook from DOMPatcher directly if it's been set on the root node

Contexts

15 Dec 00:08
Compare
Choose a tag to compare

"Contexts" allow Panel components to inject arbitrary class/object dependencies into all descendants at runtime, similarly to React Context ("Context provides a way to pass data through the component tree without having to pass props down manually at every level"). This is especially useful for data which needs to be shared globally.

Components can provide named "default contexts" for themselves and descendants in their config objects. Components similarly declare which contexts they need by providing their names in the contexts config entry. Contexts can be accessed with the getContext() method, for example for use in view templates:

get config() {
  return {
    // provided to all descendants, including itself
    defaultContexts: {
      apiCache: new SharedCache(),
      moreSharedData: {foo: `bar`},
    },

    // used in this component
    contexts: [`apiCache`, `moreSharedData`],

    // calling a method on a context provided to the current component
    template: () => h(`p`, {}, `A value from the API Cache: ${this.getContext('apiCache').someMethod()}`),
  };
}

State-initialization fixes

05 Jun 19:56
Compare
Choose a tag to compare
  • Component state is now initialized with the defaultState config value in the constructor, ensuring that default values are set even before the element is attached to the DOM
  • State updates within child components made before they enter the component tree are automatically flushed up to the shared state when the child is attached. (This now matches the existing behavior of the appState partial shared state mechanism.)

Webpack 4 support for Hot Module Replacement

18 Dec 20:36
Compare
Choose a tag to compare

Router unregisters listeners when Component disconnects from DOM

08 Nov 01:23
Compare
Choose a tag to compare

This will restore history.pushState/history.replaceState/popstate behavior when a Component that registered route handlers is removed from the DOM. Particularly useful for test suites which create/remove apps for individual test cases.

Support for declarative HTML attributes schema

08 Nov 01:18
Compare
Choose a tag to compare

For components that accept HTML attributes, attrsSchema lets them define names, types, and default values which will be populated automatically in the component's attrs prop. For example:

class MyWidget extends Component {
  static get attrsSchema() {
    return {
      ...super.attrsSchema,
      'closeable': `boolean`,
      'complex-stuff': `json`,
      'title-text': {type: `string`, default: `Hello world`},
    };
  }
}

// access within component code:
this.attrs.closeable // false

// also accessible within templates via $attrs:
$attrs[`complex-stuff`] // pre-parsed from JSON

This is an optional mechanism that helps standardize attribute-parsing and reduce attributeChangedCallback boilerplate.

Add support for `getNumberAttribute()`

08 Jun 22:09
Compare
Choose a tag to compare

ProxyComponent

13 Apr 00:18
Compare
Choose a tag to compare

Adds the ProxyComponent wrapper for switching between different component implementations at runtime, e.g.:

class MyWidget extends ProxyComponent {
  getTargetElementTag() {
    if (window.location.search.includes('enable_beta') {
      return 'my-widget-v2';
    } else {
      return 'my-widget-v1';
    }
  }
}

Other optional component utilities such as StateController and ControlledComponent have been moved into lib/component-utils, but are still exported at top level (so can still be imported like import {ProxyComponent, StateController} from 'panel';). This will however affect consumers which import directly from panel/build/ (which is not a public API and is not recommended).

`preUpdate` and `postUpdate` callback hooks

18 Mar 05:18
Compare
Choose a tag to compare

This obviates the need to override the Component update() method in order to run code on every state update (for instance for logging state changes). Overriding update() potentially required explicit overrides for every component in the tree, whereas the hooks work gracefully with cascading updates. Example usage:

get config() {
  return {
    // ...
    hooks: {
      postUpdate: () => localStorage.setItem(`latestFoo`, this.state.foo),
    },
  };
}

More useful errors when template-rendering throws an exception

09 Dec 19:39
Compare
Choose a tag to compare