Skip to content

Instantly share code, notes, and snippets.

@jamesmfriedman
Last active January 2, 2023 11:11
Show Gist options
  • Save jamesmfriedman/33c750912698f20aa9d4dda9df834e5d to your computer and use it in GitHub Desktop.
Save jamesmfriedman/33c750912698f20aa9d4dda9df834e5d to your computer and use it in GitHub Desktop.

Revisions

  1. jamesmfriedman revised this gist Nov 20, 2018. 1 changed file with 10 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions proposal.jsx
    Original file line number Diff line number Diff line change
    @@ -51,6 +51,7 @@ class extends React.Component {
    * root: {
    * classes: 'mdc-checkbox',
    * attributes: {},
    * events: {},
    * domNode: null
    * },
    * nativeControl: {
    @@ -60,6 +61,9 @@ class extends React.Component {
    * indeterminate: false
    * disabled: false
    * },
    * events: {
    * change: function
    * },
    * domNode: null
    * },
    * ...
    @@ -84,6 +88,7 @@ class extends React.Component {
    * root: {
    * classes: 'mdc-checkbox',
    * attributes: {},
    * events: {},
    * domNode: <div .../>
    * },
    * nativeControl: {
    @@ -93,6 +98,9 @@ class extends React.Component {
    * indeterminate: false
    * disabled: false
    * },
    * events: {
    * change: function
    * },
    * domNode: <input .../>
    * },
    * ...
    @@ -110,6 +118,7 @@ class extends React.Component {
    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes} {...foundation.root.attributes}>
    <input type="checkbox"
    onChange={foundation.nativeControl.events.change}
    class={foundation.nativeControl.classes}
    {...foundation.nativeControl.attributes}
    />
    @@ -145,6 +154,7 @@ class extends React.Component {
    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes} {...foundation.root.attributes}>
    <input type="checkbox"
    onChange={foundation.nativeControl.events.change}
    class={foundation.nativeControl.classes}
    {...foundation.nativeControl.attributes}
    />
  2. jamesmfriedman revised this gist Nov 20, 2018. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions proposal.jsx
    Original file line number Diff line number Diff line change
    @@ -110,7 +110,6 @@ class extends React.Component {
    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes} {...foundation.root.attributes}>
    <input type="checkbox"
    ref={(el) => (this.nativeCb = el)}
    class={foundation.nativeControl.classes}
    {...foundation.nativeControl.attributes}
    />
    @@ -146,7 +145,6 @@ class extends React.Component {
    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes} {...foundation.root.attributes}>
    <input type="checkbox"
    ref={(el) => (this.nativeCb = el)}
    class={foundation.nativeControl.classes}
    {...foundation.nativeControl.attributes}
    />
  3. jamesmfriedman revised this gist Nov 19, 2018. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions proposal.jsx
    Original file line number Diff line number Diff line change
    @@ -108,7 +108,7 @@ class extends React.Component {
    this.foundation.setState({ checked: true, disabled: false });

    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes}> {...foundation.root.attributes}
    <div ref={(el) => (this.root = el)} class={foundation.root.classes} {...foundation.root.attributes}>
    <input type="checkbox"
    ref={(el) => (this.nativeCb = el)}
    class={foundation.nativeControl.classes}
    @@ -144,7 +144,7 @@ class extends React.Component {
    this.foundation.setState({ checked: true, disabled: false });

    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes}> {...foundation.root.attributes}
    <div ref={(el) => (this.root = el)} class={foundation.root.classes} {...foundation.root.attributes}>
    <input type="checkbox"
    ref={(el) => (this.nativeCb = el)}
    class={foundation.nativeControl.classes}
  4. jamesmfriedman created this gist Nov 19, 2018.
    163 changes: 163 additions & 0 deletions proposal.jsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,163 @@
    /**
    * Current Adapter Example
    * This is a simple adapter, some are extremely complex...
    * It is not immediately obvious why some code lives in the adapter and some in the foundation
    * The Select alone is over 700 lines of component logic...
    **/
    MDCCheckboxFoundation({
    addClass: (className) => this.root_.classList.add(className),
    removeClass: (className) => this.root_.classList.remove(className),
    setNativeControlAttr: (attr, value) => this.nativeCb_.setAttribute(attr, value),
    removeNativeControlAttr: (attr) => this.nativeCb_.removeAttribute(attr),
    getNativeControl: () => this.nativeCb_,
    isIndeterminate: () => this.indeterminate,
    isChecked: () => this.checked,
    hasNativeControl: () => !!this.nativeCb_,
    setNativeControlDisabled: (disabled) => this.nativeCb_.disabled = disabled,
    forceLayout: () => this.root_.offsetWidth,
    isAttachedToDOM: () => Boolean(this.root_.parentNode),
    });

    /**
    * Proposal, turn the foundation into a state machine!
    * Instead of having the foundation figure out how to instrument behaviors,
    * have it be a declaration of what the state of the component should look like.
    * This includes a mapping of classes, attributes, and event handlers for any given element.
    *
    * This should help with just about every third party library integration.
    * This example is React, but the same applies for Angular, AngularJS, Vue, and Polymer.
    *
    * The Vanilla JS components would just have to instrument their own way to apply
    * classes and attributes, but it would be a small framework that would apply to all components.
    */
    class extends React.Component {
    constructor(props) {
    super(props);
    // create the foundation. This doesn't do any DOM manipulation, it just creates the source of truth.
    // do this here so frameworks can render the initial content with the appropriate classes

    // Removes need for
    // - addClass
    // - removeClass
    // - setNativeControlAttr
    // - removeNativeControlAttr
    // - isIndeterminate
    // - isChecked
    // - setNativeControlDisabled
    this.foundation = new CheckboxFoundation();

    /**
    * this.foundation = {
    * root: {
    * classes: 'mdc-checkbox',
    * attributes: {},
    * domNode: null
    * },
    * nativeControl: {
    * classes: 'mdc-checkbox__native-control',
    * attributes: {
    * checked: false,
    * indeterminate: false
    * disabled: false
    * },
    * domNode: null
    * },
    * ...
    * }
    */
    }

    componentDidMount() {
    // There is rendered code with classes in the DOM
    // Pass the root element and now internally you can get all of the DOM nodes you need
    // i.e. getNativeControl

    // Removes need for
    // - getNativeControl
    // - hasNativeControl
    // - isAttachedToDOM
    // - forceLayout should be the same in any framework... dont know why it has its own method
    this.foundation.getDomNodes(this.root);

    /**
    * this.foundation = {
    * root: {
    * classes: 'mdc-checkbox',
    * attributes: {},
    * domNode: <div .../>
    * },
    * nativeControl: {
    * classes: 'mdc-checkbox__native-control',
    * attributes: {
    * checked: false,
    * indeterminate: false
    * disabled: false
    * },
    * domNode: <input .../>
    * },
    * ...
    * }
    */
    }

    render() {
    // whenever we need to, we can update the foundation state
    // remember that all the foundation is doing is telling us a list of our classes and attributes
    // so this is safe to call whenever we want in our update cycle.
    // For react, we would want to call this on every render
    this.foundation.setState({ checked: true, disabled: false });

    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes}> {...foundation.root.attributes}
    <input type="checkbox"
    ref={(el) => (this.nativeCb = el)}
    class={foundation.nativeControl.classes}
    {...foundation.nativeControl.attributes}
    />
    <div class={foundation.background.classes}>
    <svg class={foundation.checkmark.classes} viewBox="0 0 24 24">
    <path class={foundation.checkmarkPath.classes} fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
    </svg>
    <div class={foundation.mixedMark.classes}></div>
    </div>
    </div>
    )
    }
    }



    /**
    * Same code, sans comments
    */
    class extends React.Component {
    constructor(props) {
    super(props);
    this.foundation = new CheckboxFoundation();
    }

    componentDidMount() {
    this.foundation.getDomNodes(this.root);
    }

    render() {
    this.foundation.setState({ checked: true, disabled: false });

    return (
    <div ref={(el) => (this.root = el)} class={foundation.root.classes}> {...foundation.root.attributes}
    <input type="checkbox"
    ref={(el) => (this.nativeCb = el)}
    class={foundation.nativeControl.classes}
    {...foundation.nativeControl.attributes}
    />
    <div class={foundation.background.classes}>
    <svg class={foundation.checkmark.classes} viewBox="0 0 24 24">
    <path class={foundation.checkmarkPath.classes} fill="none" d="M1.73,12.91 8.1,19.28 22.79,4.59" />
    </svg>
    <div class={foundation.mixedMark.classes}></div>
    </div>
    </div>
    )
    }
    }