@expressive/react
Version:
Use classes to define state in React!
176 lines (174 loc) • 5.12 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_chunk = require('./chunk-BE-pF4vm.js');
const require_context = require('./context-DEag_HVs.js');
let _expressive_state = require("@expressive/state");
//#region src/state.ts
const Pragma = {};
const OUTER = /* @__PURE__ */ new WeakMap();
const PROPS = /* @__PURE__ */ new WeakMap();
var ReactState = class ReactState extends _expressive_state.State {
/**
* Create and manage instance of this State within React component.
*
* @param args Arguments to pass to constructor or `use` method (if defined).
* @returns Managed instance of this State.
*/
static use(...args) {
const ambient = _expressive_state.Context.use();
const state = Pragma.useState(() => {
let ready;
let active;
let use = (...args) => Promise.all(args.flat().map((arg) => typeof arg == "object" && instance.set(arg)));
const instance = new this((x) => {
if (x instanceof ReactState && x.use) {
use = x.use?.bind(x);
use(...args);
} else return args;
});
const context = ambient.push(instance);
(0, _expressive_state.watch)(instance, (current) => {
active = current;
if (ready) state[1]((x) => x.bind(null));
});
function didMount() {
ready = true;
return () => {
context.pop();
instance.set(null);
};
}
return (...args) => {
Pragma.useEffect(didMount, []);
if (ready) {
ready = false;
Promise.resolve(use(...args)).finally(() => ready = true);
}
return active;
};
});
return state[0](...args);
}
static get(argument) {
const context = _expressive_state.Context.use();
const state = Pragma.useState(() => {
const instance = context.get(this);
if (!instance) if (argument === false) return () => void 0;
else throw new Error(`Could not find ${this} in context.`);
let ready;
let value;
function render() {
state[1]((x) => x.bind(null));
}
function refresh(action) {
if (typeof action == "function") action = action();
render();
if (action) return action.finally(render);
}
const unwatch = (0, _expressive_state.watch)(instance, (current) => {
if (typeof argument === "function") {
const next = argument.call(current, current, refresh);
if (next === value) return;
value = next;
} else value = current;
if (ready) render();
}, argument === true);
if (value instanceof Promise) {
let error;
unwatch();
value.then((x) => value = x, (e) => error = e).finally(render);
value = null;
return () => {
if (error) throw error;
return value === void 0 ? null : value;
};
}
if (value === null) {
unwatch();
return () => null;
}
function onMount() {
ready = true;
return unwatch;
}
return () => {
Pragma.useEffect(onMount, []);
return value === void 0 ? null : value;
};
});
return state[0]();
}
static as(argument) {
const Type = this;
const render = typeof argument === "function" ? argument : void 0;
class ReactType extends Type {
static {
this.contextType = require_context.Layers;
}
get props() {
return PROPS.get(this);
}
set props(props) {
PROPS.set(this, props);
this.set(props);
}
get context() {
return _expressive_state.Context.get(this);
}
set context(context) {
if (OUTER.get(this) === context) return;
OUTER.set(this, context);
context.push(this);
}
get state() {
return this.get();
}
set state(_state) {}
constructor(nextProps, ...rest) {
const { is } = nextProps;
const defaults = typeof argument === "object" ? argument : {};
if (rest[0] instanceof _expressive_state.Context) rest.shift();
super(nextProps, defaults, is, rest);
this.fallback = void 0;
PROPS.set(this, nextProps);
if (render) {
const Self = Render.bind(this, render);
this.render = () => Pragma.createElement(Self);
} else if (!this.render) this.render = () => require_context.provide(this.context, this.props.children || null, this.props.fallback, String(this));
}
}
Object.defineProperty(ReactType, "name", { value: "React" + this.name });
Object.defineProperty(ReactType.prototype, "isReactComponent", { get: () => true });
return ReactType;
}
};
function Render(render) {
const state = Pragma.useState(() => {
(0, _expressive_state.event)(this);
const { context } = this;
let ready;
let active;
(0, _expressive_state.watch)(this, (current) => {
active = current;
if (ready) state[1]((x) => x.bind(null));
});
const didMount = () => {
ready = true;
return () => {
context.pop();
this.set(null);
};
};
const View = () => render.call(active, this.props, active);
return () => {
ready = false;
Pragma.useEffect(didMount, []);
setTimeout(() => ready = true, 0);
return require_context.provide(context, Pragma.createElement(View), this.props.fallback, String(this));
};
});
return state[0]();
}
//#endregion
exports.Pragma = Pragma;
exports.ReactState = ReactState;
//# sourceMappingURL=state.js.map