Skip to content

Instantly share code, notes, and snippets.

@lifeart
Last active October 11, 2020 10:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lifeart/53d69c77f7e8f8f9cd07ee9ddc224714 to your computer and use it in GitHub Desktop.
Save lifeart/53d69c77f7e8f8f9cd07ee9ddc224714 to your computer and use it in GitHub Desktop.
Glimmer Composition API
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { tracked as trackedAny } from 'tracked-built-ins';
const IS_REF = Symbol("IS_REF");
class TrackedRef {
[IS_REF] = true;
constructor(initialValue) {
this.value = initialValue;
}
@tracked value;
}
function reactive(obj) {
return trackedAny(obj);
}
function isRef(obj) {
return obj[IS_REF] || false;
}
class TrackedWrapper {
[IS_REF] = true;
@tracked _value;
constructor(obj) {
this.value = obj;
}
get value() {
return this._value;
}
set value(val) {
this._value = trackedAny(val);
}
}
class TrackedObjectKeyRef {
[IS_REF] = true;
constructor(obj, key) {
this.obj = obj;
this.key = key;
}
get value() {
return unref(this.obj)[this.key];
}
set value(value) {
unref(this.obj)[this.key] = value;
}
}
function toRef(obj, key) {
return new TrackedObjectKeyRef(obj, key);
}
function unref(trackedRef) {
return isRef(trackedRef) ? trackedRef.value : trackedRef;
}
function ref(value) {
return new TrackedRef(value);
}
function customRef(fn) {
const ref = new CustomRefWrapper();
const track = ()=>{ ref.value; };
const trigger = ()=>{ ref.value++; };
const {get, set} = fn(track, trigger);
return new CustomRef({get, set});
}
class CustomRef {
[IS_REF] = true;
constructor(desc) {
this.desc = desc;
}
get value() {
return this.desc.get();
}
set value(value) {
this.desc.set(value);
}
}
class CustomRefWrapper {
@tracked value;
}
function toRefs(state) {
const result = {};
const pureState = state;
Object.keys(unref(state)).forEach((key)=>{
result[key] = toRef(pureState, key);
});
return result;
}
export default class extends Component {
constructor() {
super(...arguments);
const props = this.setup(this.args);
Object.entries(props).forEach(([key, value])=>{
Object.defineProperty(this, key, {
get() {
return value.value;
},
set(value) {
value.value = value;
}
});
});
}
setup() {
const user = reactive({name: 'foo'});
//const name = toRef(user, 'name');
const name = customRef((track, trigger)=>{
return {
get() {
track();
return 42;
},
set() {
trigger();
return 12;
}
}
});
const state = toRefs(user);
console.log(user);
setInterval(()=>{ user.name = Date.now() },1000);
return {
name: state.name
}
}
}
import Controller from '@ember/controller';
export default class ApplicationController extends Controller {
appName = 'Ember Twiddle';
}
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0",
"tracked-built-ins": "1.0.2"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment