@xihan-ui/web-components 1.0.0-alpha.1 → 1.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +589 -0
- package/custom-elements.json +18815 -4447
- package/dist/backgrounds.js +1 -1
- package/dist/config-Cz16-P4i.d.ts +37 -0
- package/dist/config-Cz16-P4i.d.ts.map +1 -0
- package/dist/define.d.ts +2419 -266
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +4213 -978
- package/dist/define.js.map +1 -1
- package/dist/{element-BxtVEMuI.js → element-Cpkqkn_U.js} +2 -2
- package/dist/{element-BxtVEMuI.js.map → element-Cpkqkn_U.js.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{machine-controller-Cq9t_cfJ.js → machine-controller-j_fnUsFq.js} +68 -4
- package/dist/machine-controller-j_fnUsFq.js.map +1 -0
- package/package.json +19 -17
- package/dist/machine-controller-Cq9t_cfJ.js.map +0 -1
- package/dist/spread-Ch8ZXZDC.d.ts +0 -9
- package/dist/spread-Ch8ZXZDC.d.ts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region package.json
|
|
2
|
-
var version = "1.0.0-alpha.
|
|
2
|
+
var version = "1.0.0-alpha.3";
|
|
3
3
|
//#endregion
|
|
4
4
|
//#region src/reactive/element.ts
|
|
5
5
|
const finalizedClasses = /* @__PURE__ */ new WeakSet();
|
|
@@ -248,4 +248,4 @@ attributeMaps.set(XhReactiveElement, /* @__PURE__ */ new Map());
|
|
|
248
248
|
//#endregion
|
|
249
249
|
export { version as n, XhReactiveElement as t };
|
|
250
250
|
|
|
251
|
-
//# sourceMappingURL=element-
|
|
251
|
+
//# sourceMappingURL=element-Cpkqkn_U.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element-BxtVEMuI.js","names":[],"sources":["../package.json","../src/reactive/element.ts"],"sourcesContent":["","import type {\n AttributeConverter,\n PropertyDeclaration,\n PropertyDeclarations,\n PropertyValues,\n ReactiveController,\n ReactiveControllerHost,\n} from './types'\n\n// 定稿过的类,键是构造器本身;子类各登记一次。\nconst finalizedClasses = new WeakSet<object>()\n// 每个类的:属性名 → 字段名。\nconst attributeMaps = new WeakMap<object, Map<string, string>>()\n// 每个原型上由 createProperty 装过访问器的字段名。\nconst installedAccessors = new WeakMap<object, Set<string>>()\n// 声明里实现了的键,其余一律抛。\nconst SUPPORTED_DECLARATION_KEYS = new Set(['attribute', 'converter', 'type'])\n\n/** 按声明的 type 解读属性字符串。 */\nfunction defaultFromAttribute(value: string | null, type?: unknown): unknown {\n switch (type) {\n case Boolean:\n return value !== null\n case Number:\n return value === null ? null : Number(value)\n case Object:\n case Array:\n try {\n return JSON.parse(value!) as unknown\n }\n catch {\n return null\n }\n default:\n return value\n }\n}\n\nfunction fromAttributeOf(options: PropertyDeclaration): (value: string | null, type?: unknown) => unknown {\n const converter = options.converter as AttributeConverter | undefined\n if (typeof converter === 'function')\n return converter\n return converter?.fromAttribute ?? defaultFromAttribute\n}\n\n/** 判等:Object.is 同值不排更新(NaN 与 NaN 同值,+0 与 -0 不同值)。声明里不接受自定义 hasChanged。 */\nfunction valueChanged(value: unknown, old: unknown): boolean {\n return !Object.is(value, old)\n}\n\n/** 让本类持有自己的 elementProperties。未定稿时顺原型链读到的是父类那一个 Map 实例,直接写会污染父类并泄漏给兄弟子类。 */\nfunction prepareOwnProperties(ctor: typeof XhReactiveElement): void {\n if (Object.hasOwn(ctor, 'elementProperties'))\n return\n const superCtor = Object.getPrototypeOf(ctor) as typeof XhReactiveElement\n ctor.elementProperties = new Map(superCtor.elementProperties)\n}\n\n/** 声明键只认 attribute / converter / type,其余当场抛(Lit 的那几个键在这里不生效,不能静默吞)。 */\nfunction assertSupportedDeclaration(ctor: typeof XhReactiveElement, name: string, options: PropertyDeclaration): void {\n for (const key of Reflect.ownKeys(options)) {\n if (typeof key === 'string' && SUPPORTED_DECLARATION_KEYS.has(key))\n continue\n throw new TypeError(\n `${ctor.name}.properties.${name}: 不支持的声明键 ${String(key)}。`\n + `本运行时只实现 attribute / converter / type:不回写属性(无 reflect)、判等固定 Object.is(无 hasChanged)、声明必装访问器(无 noAccessor / state)。`,\n )\n }\n}\n\n/** 原型上已有同名成员就抛:装访问器会把它整块盖掉,此后作者写的 get/set 或方法永不被调用。 */\nfunction assertPrototypeFree(ctor: typeof XhReactiveElement, name: string): void {\n if (installedAccessors.get(ctor.prototype)?.has(name))\n return\n const existing = Object.getOwnPropertyDescriptor(ctor.prototype, name)\n if (existing === undefined)\n return\n const kind = existing.get !== undefined || existing.set !== undefined ? 'get/set 访问器' : '成员'\n throw new TypeError(\n `${ctor.name}.prototype.${name} 已有 ${kind},响应式属性会把它整块盖掉。`\n + `本运行时不做 Lit 那样的包装:请给字段改名,或删掉 ${ctor.name}.properties.${name} 这条声明。`,\n )\n}\n\n/** 该字段观察哪个属性;undefined 表示不观察。 */\nfunction attributeNameFor(name: string, options: PropertyDeclaration): string | undefined {\n const { attribute } = options\n if (attribute === false)\n return undefined\n return typeof attribute === 'string' ? attribute : name.toLowerCase()\n}\n\n/**\n * 无 DOM 时的基座替身。类定义式在模块求值那一刻就会取 HTMLElement,\n * 而任何 meta-framework 都会在 Node 里把入口模块求值一次。\n * 元素在没有 customElements 的环境里本就不会被注册,替身只需让定义式成立。\n */\nconst HostBase: typeof HTMLElement\n = typeof HTMLElement === 'undefined'\n ? (class {} as unknown as typeof HTMLElement)\n : HTMLElement\n\n/**\n * 响应式自定义元素基类:属性 → 字段的单向转换、批量异步更新、控制器生命周期。\n * 不做 shadow DOM、不做样式、不做模板渲染、不回写属性。\n */\nexport class XhReactiveElement extends HostBase implements ReactiveControllerHost {\n /** 子类以 `static properties = { 字段名: 选项 }` 声明响应式属性。 */\n static properties: PropertyDeclarations = {}\n\n /** 定稿后的全部声明,含从父类继承来的。 */\n static elementProperties: Map<string, PropertyDeclaration> = new Map()\n\n /** 浏览器在 customElements.define() 时读它,属性声明就在这一刻定稿。本基类自身返回 [](Lit 那边是 undefined)。 */\n static get observedAttributes(): string[] {\n this.finalize()\n const attrs = attributeMaps.get(this)\n return attrs === undefined ? [] : [...attrs.keys()]\n }\n\n /** 合并父类声明并逐条建访问器。递归到本基类为止(它已预先登记为定稿);中途抛错时不登记,下次读还抛同一条。 */\n protected static finalize(): void {\n if (finalizedClasses.has(this))\n return\n const superCtor = Object.getPrototypeOf(this) as typeof XhReactiveElement\n superCtor.finalize()\n prepareOwnProperties(this)\n if (Object.hasOwn(this, 'properties')) {\n const declarations = this.properties\n const symbols = Object.getOwnPropertySymbols(declarations)\n if (symbols.length > 0) {\n throw new TypeError(\n `${this.name}.properties 含 symbol 键 ${String(symbols[0])}:只支持字符串键(symbol 键映射不出属性名)。`,\n )\n }\n for (const name of Object.getOwnPropertyNames(declarations))\n this.createProperty(name, declarations[name] ?? {})\n }\n // 声明全部并完再算属性映射:子类给同名字段改了属性名时,基类那个旧属性名要随之作废。\n const attributes = new Map<string, string>()\n for (const [name, options] of this.elementProperties) {\n const attribute = attributeNameFor(name, options)\n if (attribute !== undefined)\n attributes.set(attribute, name)\n }\n attributeMaps.set(this, attributes)\n finalizedClasses.add(this)\n }\n\n /** 登记一条声明,并在原型上装一个\"写入即排更新\"的访问器。 */\n protected static createProperty(name: string, options: PropertyDeclaration): void {\n prepareOwnProperties(this)\n assertSupportedDeclaration(this, name, options)\n assertPrototypeFree(this, name)\n this.elementProperties.set(name, options)\n const key = Symbol(name)\n Object.defineProperty(this.prototype, name, {\n configurable: true,\n enumerable: true,\n get(this: Record<symbol, unknown>): unknown {\n return this[key]\n },\n set(this: Record<symbol, unknown> & XhReactiveElement, value: unknown) {\n const old = this[key]\n this[key] = value\n this.requestUpdate(name, old)\n },\n })\n const installed = installedAccessors.get(this.prototype) ?? new Set<string>()\n installed.add(name)\n installedAccessors.set(this.prototype, installed)\n }\n\n /** createRenderRoot() 的产物。 */\n renderRoot!: HTMLElement | DocumentFragment\n\n private readonly controllers = new Set<ReactiveController>()\n private changedProperties: PropertyValues = new Map()\n private pendingUpdate = false\n private hasUpdated = false\n /** 升级前就写在实例上的字段值,首轮更新时补写回去。 */\n private instanceProperties: Map<string, unknown> | undefined\n private updatePromise!: Promise<boolean>\n private startUpdating!: (value: boolean) => void\n\n constructor() {\n super()\n // 首轮更新等这个闸口,connectedCallback 才放行。\n this.updatePromise = new Promise<boolean>((resolve) => {\n this.startUpdating = resolve\n })\n this.saveInstanceProperties()\n this.requestUpdate()\n }\n\n /** 元素还没 upgrade 时被赋的字段值会盖住原型访问器,先摘下来存着。 */\n private saveInstanceProperties(): void {\n const self = this as unknown as Record<string, unknown>\n for (const name of (this.constructor as typeof XhReactiveElement).elementProperties.keys()) {\n if (!Object.hasOwn(this, name))\n continue\n this.instanceProperties ??= new Map()\n this.instanceProperties.set(name, self[name])\n delete self[name]\n }\n }\n\n /** 渲染根,默认就是元素自己(Light DOM)。 */\n protected createRenderRoot(): HTMLElement | DocumentFragment {\n return this\n }\n\n addController(controller: ReactiveController): void {\n this.controllers.add(controller)\n // 已经连上了就当场补一次 hostConnected(控制器常在字段初始化里注册,那时 connected 已过)。\n if (this.renderRoot !== undefined && this.isConnected)\n controller.hostConnected?.()\n }\n\n removeController(controller: ReactiveController): void {\n this.controllers.delete(controller)\n }\n\n connectedCallback(): void {\n this.renderRoot ??= this.createRenderRoot()\n this.startUpdating(true)\n for (const controller of this.controllers) controller.hostConnected?.()\n }\n\n disconnectedCallback(): void {\n for (const controller of this.controllers) controller.hostDisconnected?.()\n }\n\n /** 属性变化转成字段值;单向,不回写属性。 */\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n const ctor = this.constructor as typeof XhReactiveElement\n const property = attributeMaps.get(ctor)?.get(name)\n if (property === undefined)\n return\n const options = ctor.elementProperties.get(property) ?? {}\n const self = this as unknown as Record<string, unknown>\n self[property] = fromAttributeOf(options)(value, options.type)\n }\n\n /**\n * 排一轮更新。带 name 时先按判等过滤,同值直接返回。\n * 一拍内调多次只排一轮。\n */\n requestUpdate(name?: PropertyKey, oldValue?: unknown): void {\n if (name !== undefined) {\n const value = (this as unknown as Record<PropertyKey, unknown>)[name]\n if (!valueChanged(value, oldValue))\n return\n // 首轮更新跑完之前,changedProperties 里的旧值一律记 undefined。\n if (!this.changedProperties.has(name))\n this.changedProperties.set(name, this.hasUpdated ? oldValue : undefined)\n }\n if (!this.pendingUpdate)\n this.updatePromise = this.enqueueUpdate()\n }\n\n /**\n * 本轮更新落定后 resolve;值为 false 表示更新过程中又排了新一轮(要等的是新的 updateComplete)。\n * 元素连上之前永不 resolve。\n */\n get updateComplete(): Promise<boolean> {\n return this.updatePromise\n }\n\n private async enqueueUpdate(): Promise<boolean> {\n this.pendingUpdate = true\n try {\n await this.updatePromise\n }\n catch (error) {\n // 上一轮的失败不拖住这一轮,但也不吞掉,抛成未处理拒绝。\n void Promise.reject(error)\n }\n this.performUpdate()\n return !this.pendingUpdate\n }\n\n private performUpdate(): void {\n if (!this.pendingUpdate)\n return\n if (!this.hasUpdated && this.instanceProperties) {\n const self = this as unknown as Record<string, unknown>\n for (const [name, value] of this.instanceProperties) self[name] = value\n this.instanceProperties = undefined\n }\n const changed = this.changedProperties\n try {\n for (const controller of this.controllers) controller.hostUpdate?.()\n this.update(changed)\n }\n catch (error) {\n this.markUpdated()\n throw error\n }\n for (const controller of this.controllers) controller.hostUpdated?.()\n if (!this.hasUpdated) {\n this.hasUpdated = true\n this.firstUpdated(changed)\n }\n this.updated(changed)\n }\n\n private markUpdated(): void {\n this.changedProperties = new Map()\n this.pendingUpdate = false\n }\n\n /** 更新主体。子类覆盖时必须调 super.update(),否则这轮永远结不掉。 */\n protected update(_changed: PropertyValues): void {\n this.markUpdated()\n }\n\n /** 首轮更新后调一次。 */\n protected firstUpdated(_changed: PropertyValues): void {}\n\n /** 每轮更新后调。 */\n protected updated(_changed: PropertyValues): void {}\n}\n\n// 递归定稿的终点:本基类自己没有属性声明。\nfinalizedClasses.add(XhReactiveElement)\nattributeMaps.set(XhReactiveElement, new Map())\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"element-Cpkqkn_U.js","names":[],"sources":["../package.json","../src/reactive/element.ts"],"sourcesContent":["","import type {\n AttributeConverter,\n PropertyDeclaration,\n PropertyDeclarations,\n PropertyValues,\n ReactiveController,\n ReactiveControllerHost,\n} from './types'\n\n// 定稿过的类,键是构造器本身;子类各登记一次。\nconst finalizedClasses = new WeakSet<object>()\n// 每个类的:属性名 → 字段名。\nconst attributeMaps = new WeakMap<object, Map<string, string>>()\n// 每个原型上由 createProperty 装过访问器的字段名。\nconst installedAccessors = new WeakMap<object, Set<string>>()\n// 声明里实现了的键,其余一律抛。\nconst SUPPORTED_DECLARATION_KEYS = new Set(['attribute', 'converter', 'type'])\n\n/** 按声明的 type 解读属性字符串。 */\nfunction defaultFromAttribute(value: string | null, type?: unknown): unknown {\n switch (type) {\n case Boolean:\n return value !== null\n case Number:\n return value === null ? null : Number(value)\n case Object:\n case Array:\n try {\n return JSON.parse(value!) as unknown\n }\n catch {\n return null\n }\n default:\n return value\n }\n}\n\nfunction fromAttributeOf(options: PropertyDeclaration): (value: string | null, type?: unknown) => unknown {\n const converter = options.converter as AttributeConverter | undefined\n if (typeof converter === 'function')\n return converter\n return converter?.fromAttribute ?? defaultFromAttribute\n}\n\n/** 判等:Object.is 同值不排更新(NaN 与 NaN 同值,+0 与 -0 不同值)。声明里不接受自定义 hasChanged。 */\nfunction valueChanged(value: unknown, old: unknown): boolean {\n return !Object.is(value, old)\n}\n\n/** 让本类持有自己的 elementProperties。未定稿时顺原型链读到的是父类那一个 Map 实例,直接写会污染父类并泄漏给兄弟子类。 */\nfunction prepareOwnProperties(ctor: typeof XhReactiveElement): void {\n if (Object.hasOwn(ctor, 'elementProperties'))\n return\n const superCtor = Object.getPrototypeOf(ctor) as typeof XhReactiveElement\n ctor.elementProperties = new Map(superCtor.elementProperties)\n}\n\n/** 声明键只认 attribute / converter / type,其余当场抛(Lit 的那几个键在这里不生效,不能静默吞)。 */\nfunction assertSupportedDeclaration(ctor: typeof XhReactiveElement, name: string, options: PropertyDeclaration): void {\n for (const key of Reflect.ownKeys(options)) {\n if (typeof key === 'string' && SUPPORTED_DECLARATION_KEYS.has(key))\n continue\n throw new TypeError(\n `${ctor.name}.properties.${name}: 不支持的声明键 ${String(key)}。`\n + `本运行时只实现 attribute / converter / type:不回写属性(无 reflect)、判等固定 Object.is(无 hasChanged)、声明必装访问器(无 noAccessor / state)。`,\n )\n }\n}\n\n/** 原型上已有同名成员就抛:装访问器会把它整块盖掉,此后作者写的 get/set 或方法永不被调用。 */\nfunction assertPrototypeFree(ctor: typeof XhReactiveElement, name: string): void {\n if (installedAccessors.get(ctor.prototype)?.has(name))\n return\n const existing = Object.getOwnPropertyDescriptor(ctor.prototype, name)\n if (existing === undefined)\n return\n const kind = existing.get !== undefined || existing.set !== undefined ? 'get/set 访问器' : '成员'\n throw new TypeError(\n `${ctor.name}.prototype.${name} 已有 ${kind},响应式属性会把它整块盖掉。`\n + `本运行时不做 Lit 那样的包装:请给字段改名,或删掉 ${ctor.name}.properties.${name} 这条声明。`,\n )\n}\n\n/** 该字段观察哪个属性;undefined 表示不观察。 */\nfunction attributeNameFor(name: string, options: PropertyDeclaration): string | undefined {\n const { attribute } = options\n if (attribute === false)\n return undefined\n return typeof attribute === 'string' ? attribute : name.toLowerCase()\n}\n\n/**\n * 无 DOM 时的基座替身。类定义式在模块求值那一刻就会取 HTMLElement,\n * 而任何 meta-framework 都会在 Node 里把入口模块求值一次。\n * 元素在没有 customElements 的环境里本就不会被注册,替身只需让定义式成立。\n */\nconst HostBase: typeof HTMLElement\n = typeof HTMLElement === 'undefined'\n ? (class {} as unknown as typeof HTMLElement)\n : HTMLElement\n\n/**\n * 响应式自定义元素基类:属性 → 字段的单向转换、批量异步更新、控制器生命周期。\n * 不做 shadow DOM、不做样式、不做模板渲染、不回写属性。\n */\nexport class XhReactiveElement extends HostBase implements ReactiveControllerHost {\n /** 子类以 `static properties = { 字段名: 选项 }` 声明响应式属性。 */\n static properties: PropertyDeclarations = {}\n\n /** 定稿后的全部声明,含从父类继承来的。 */\n static elementProperties: Map<string, PropertyDeclaration> = new Map()\n\n /** 浏览器在 customElements.define() 时读它,属性声明就在这一刻定稿。本基类自身返回 [](Lit 那边是 undefined)。 */\n static get observedAttributes(): string[] {\n this.finalize()\n const attrs = attributeMaps.get(this)\n return attrs === undefined ? [] : [...attrs.keys()]\n }\n\n /** 合并父类声明并逐条建访问器。递归到本基类为止(它已预先登记为定稿);中途抛错时不登记,下次读还抛同一条。 */\n protected static finalize(): void {\n if (finalizedClasses.has(this))\n return\n const superCtor = Object.getPrototypeOf(this) as typeof XhReactiveElement\n superCtor.finalize()\n prepareOwnProperties(this)\n if (Object.hasOwn(this, 'properties')) {\n const declarations = this.properties\n const symbols = Object.getOwnPropertySymbols(declarations)\n if (symbols.length > 0) {\n throw new TypeError(\n `${this.name}.properties 含 symbol 键 ${String(symbols[0])}:只支持字符串键(symbol 键映射不出属性名)。`,\n )\n }\n for (const name of Object.getOwnPropertyNames(declarations))\n this.createProperty(name, declarations[name] ?? {})\n }\n // 声明全部并完再算属性映射:子类给同名字段改了属性名时,基类那个旧属性名要随之作废。\n const attributes = new Map<string, string>()\n for (const [name, options] of this.elementProperties) {\n const attribute = attributeNameFor(name, options)\n if (attribute !== undefined)\n attributes.set(attribute, name)\n }\n attributeMaps.set(this, attributes)\n finalizedClasses.add(this)\n }\n\n /** 登记一条声明,并在原型上装一个\"写入即排更新\"的访问器。 */\n protected static createProperty(name: string, options: PropertyDeclaration): void {\n prepareOwnProperties(this)\n assertSupportedDeclaration(this, name, options)\n assertPrototypeFree(this, name)\n this.elementProperties.set(name, options)\n const key = Symbol(name)\n Object.defineProperty(this.prototype, name, {\n configurable: true,\n enumerable: true,\n get(this: Record<symbol, unknown>): unknown {\n return this[key]\n },\n set(this: Record<symbol, unknown> & XhReactiveElement, value: unknown) {\n const old = this[key]\n this[key] = value\n this.requestUpdate(name, old)\n },\n })\n const installed = installedAccessors.get(this.prototype) ?? new Set<string>()\n installed.add(name)\n installedAccessors.set(this.prototype, installed)\n }\n\n /** createRenderRoot() 的产物。 */\n renderRoot!: HTMLElement | DocumentFragment\n\n private readonly controllers = new Set<ReactiveController>()\n private changedProperties: PropertyValues = new Map()\n private pendingUpdate = false\n private hasUpdated = false\n /** 升级前就写在实例上的字段值,首轮更新时补写回去。 */\n private instanceProperties: Map<string, unknown> | undefined\n private updatePromise!: Promise<boolean>\n private startUpdating!: (value: boolean) => void\n\n constructor() {\n super()\n // 首轮更新等这个闸口,connectedCallback 才放行。\n this.updatePromise = new Promise<boolean>((resolve) => {\n this.startUpdating = resolve\n })\n this.saveInstanceProperties()\n this.requestUpdate()\n }\n\n /** 元素还没 upgrade 时被赋的字段值会盖住原型访问器,先摘下来存着。 */\n private saveInstanceProperties(): void {\n const self = this as unknown as Record<string, unknown>\n for (const name of (this.constructor as typeof XhReactiveElement).elementProperties.keys()) {\n if (!Object.hasOwn(this, name))\n continue\n this.instanceProperties ??= new Map()\n this.instanceProperties.set(name, self[name])\n delete self[name]\n }\n }\n\n /** 渲染根,默认就是元素自己(Light DOM)。 */\n protected createRenderRoot(): HTMLElement | DocumentFragment {\n return this\n }\n\n addController(controller: ReactiveController): void {\n this.controllers.add(controller)\n // 已经连上了就当场补一次 hostConnected(控制器常在字段初始化里注册,那时 connected 已过)。\n if (this.renderRoot !== undefined && this.isConnected)\n controller.hostConnected?.()\n }\n\n removeController(controller: ReactiveController): void {\n this.controllers.delete(controller)\n }\n\n connectedCallback(): void {\n this.renderRoot ??= this.createRenderRoot()\n this.startUpdating(true)\n for (const controller of this.controllers) controller.hostConnected?.()\n }\n\n disconnectedCallback(): void {\n for (const controller of this.controllers) controller.hostDisconnected?.()\n }\n\n /** 属性变化转成字段值;单向,不回写属性。 */\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n const ctor = this.constructor as typeof XhReactiveElement\n const property = attributeMaps.get(ctor)?.get(name)\n if (property === undefined)\n return\n const options = ctor.elementProperties.get(property) ?? {}\n const self = this as unknown as Record<string, unknown>\n self[property] = fromAttributeOf(options)(value, options.type)\n }\n\n /**\n * 排一轮更新。带 name 时先按判等过滤,同值直接返回。\n * 一拍内调多次只排一轮。\n */\n requestUpdate(name?: PropertyKey, oldValue?: unknown): void {\n if (name !== undefined) {\n const value = (this as unknown as Record<PropertyKey, unknown>)[name]\n if (!valueChanged(value, oldValue))\n return\n // 首轮更新跑完之前,changedProperties 里的旧值一律记 undefined。\n if (!this.changedProperties.has(name))\n this.changedProperties.set(name, this.hasUpdated ? oldValue : undefined)\n }\n if (!this.pendingUpdate)\n this.updatePromise = this.enqueueUpdate()\n }\n\n /**\n * 本轮更新落定后 resolve;值为 false 表示更新过程中又排了新一轮(要等的是新的 updateComplete)。\n * 元素连上之前永不 resolve。\n */\n get updateComplete(): Promise<boolean> {\n return this.updatePromise\n }\n\n private async enqueueUpdate(): Promise<boolean> {\n this.pendingUpdate = true\n try {\n await this.updatePromise\n }\n catch (error) {\n // 上一轮的失败不拖住这一轮,但也不吞掉,抛成未处理拒绝。\n void Promise.reject(error)\n }\n this.performUpdate()\n return !this.pendingUpdate\n }\n\n private performUpdate(): void {\n if (!this.pendingUpdate)\n return\n if (!this.hasUpdated && this.instanceProperties) {\n const self = this as unknown as Record<string, unknown>\n for (const [name, value] of this.instanceProperties) self[name] = value\n this.instanceProperties = undefined\n }\n const changed = this.changedProperties\n try {\n for (const controller of this.controllers) controller.hostUpdate?.()\n this.update(changed)\n }\n catch (error) {\n this.markUpdated()\n throw error\n }\n for (const controller of this.controllers) controller.hostUpdated?.()\n if (!this.hasUpdated) {\n this.hasUpdated = true\n this.firstUpdated(changed)\n }\n this.updated(changed)\n }\n\n private markUpdated(): void {\n this.changedProperties = new Map()\n this.pendingUpdate = false\n }\n\n /** 更新主体。子类覆盖时必须调 super.update(),否则这轮永远结不掉。 */\n protected update(_changed: PropertyValues): void {\n this.markUpdated()\n }\n\n /** 首轮更新后调一次。 */\n protected firstUpdated(_changed: PropertyValues): void {}\n\n /** 每轮更新后调。 */\n protected updated(_changed: PropertyValues): void {}\n}\n\n// 递归定稿的终点:本基类自己没有属性声明。\nfinalizedClasses.add(XhReactiveElement)\nattributeMaps.set(XhReactiveElement, new Map())\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as ReactiveControllerHost, i as ReactiveController } from "./types-BvWWqMd_.js";
|
|
2
|
-
import { n as
|
|
2
|
+
import { a as mergeXhConfig, c as setXhConfig, i as getXhConfig, l as Spreader, n as XhConfigScope, o as onXhConfigChange, r as XhTranslationOverrides, s as resolveXhConfig, t as XhConfig, u as createSpreader } from "./config-Cz16-P4i.js";
|
|
3
3
|
import { Scope } from "@xihan-ui/kernel";
|
|
4
4
|
import { MachineConfig, MachineSchema, ReactiveRuntime, Service } from "@xihan-ui/machine";
|
|
5
5
|
//#region src/dom/normalize.d.ts
|
|
@@ -28,12 +28,12 @@ interface MachineControllerOptions<T extends MachineSchema> {
|
|
|
28
28
|
declare class MachineController<T extends MachineSchema> implements ReactiveController {
|
|
29
29
|
private readonly host;
|
|
30
30
|
private readonly machine;
|
|
31
|
-
private readonly props;
|
|
32
31
|
private readonly opts;
|
|
33
32
|
service: Service<T>;
|
|
34
33
|
private runtime;
|
|
35
34
|
private started;
|
|
36
35
|
private formReset;
|
|
36
|
+
private readonly props;
|
|
37
37
|
constructor(host: ReactiveControllerHost, machine: MachineConfig<T>, props: () => Partial<T['props']>, opts?: MachineControllerOptions<T>);
|
|
38
38
|
private build;
|
|
39
39
|
hostConnected(): void;
|
|
@@ -46,5 +46,5 @@ declare class MachineController<T extends MachineSchema> implements ReactiveCont
|
|
|
46
46
|
//#region src/runtime/registry.d.ts
|
|
47
47
|
declare function defineElement(tag: string, ctor: CustomElementConstructor, version: string): void;
|
|
48
48
|
//#endregion
|
|
49
|
-
export { type LitRuntime, MachineController, type Spreader, createLitRuntime, createSpreader, defineElement, discoverParts, wcNormalize };
|
|
49
|
+
export { type LitRuntime, MachineController, type Spreader, type XhConfig, type XhConfigScope, type XhTranslationOverrides, createLitRuntime, createSpreader, defineElement, discoverParts, getXhConfig, mergeXhConfig, onXhConfigChange, resolveXhConfig, setXhConfig, wcNormalize };
|
|
50
50
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/dom/normalize.ts","../src/dom/parts.ts","../src/runtime/lit-runtime.ts","../src/runtime/machine-controller.ts","../src/runtime/registry.ts"],"mappings":";;;;;cAGa,wCAAW,0CAAA,qCAAA;;;iBCMR,cAAc,MAAM,cAAc,YAAY;;;UCJ7C,mBAAmB;;EAElC;;EAEA;;EAEA;;iBAYc,iBAAiB,MAAM,yBAAyB;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/dom/normalize.ts","../src/dom/parts.ts","../src/runtime/lit-runtime.ts","../src/runtime/machine-controller.ts","../src/runtime/registry.ts"],"mappings":";;;;;cAGa,wCAAW,0CAAA,qCAAA;;;iBCMR,cAAc,MAAM,cAAc,YAAY;;;UCJ7C,mBAAmB;;EAElC;;EAEA;;EAEA;;iBAYc,iBAAiB,MAAM,yBAAyB;;;UCb/C,yBAAyB,UAAU;EAClD,QAAQ;;EAER,WAAW,SAAS,QAAQ;;cAIjB,kBAAkB,UAAU,0BAA0B;mBAS9C;mBACA;mBAEA;EAXnB,SAAU,QAAQ;UACV;UACA;UACA;mBAES;EAGE,YAAA,MAAM,wBACN,SAAS,cAAc,IACxC,aAAa,QAAQ,aACJ,OAAM,yBAAyB;UAS1C;EAMR;;UAYQ;EAeR;EAIA;;;;iBC9Dc,cAAc,aAAa,MAAM,0BAA0B"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as createLitRuntime, o as discoverParts, r as createSpreader, s as wcNormalize, t as MachineController } from "./machine-controller-
|
|
1
|
+
import { f as onXhConfigChange, l as getXhConfig, m as setXhConfig, n as createLitRuntime, o as discoverParts, p as resolveXhConfig, r as createSpreader, s as wcNormalize, t as MachineController, u as mergeXhConfig } from "./machine-controller-j_fnUsFq.js";
|
|
2
2
|
import { t as defineElement } from "./registry-DR6I2_zF.js";
|
|
3
|
-
export { MachineController, createLitRuntime, createSpreader, defineElement, discoverParts, wcNormalize };
|
|
3
|
+
export { MachineController, createLitRuntime, createSpreader, defineElement, discoverParts, getXhConfig, mergeXhConfig, onXhConfigChange, resolveXhConfig, setXhConfig, wcNormalize };
|
|
@@ -1,6 +1,70 @@
|
|
|
1
|
+
import { mergeXhConfig, withXhConfigBase } from "@xihan-ui/headless";
|
|
2
|
+
import { setMotionOverride } from "@xihan-ui/motion";
|
|
1
3
|
import { createNormalizer } from "@xihan-ui/kernel";
|
|
2
4
|
import { createFormResetBridge } from "@xihan-ui/behavior";
|
|
3
5
|
import { FORM_RESET_EVENT, createService, declaresFormReset } from "@xihan-ui/machine";
|
|
6
|
+
//#region src/config.ts
|
|
7
|
+
let current = {};
|
|
8
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
9
|
+
/** 配置变了就叫一遍:全局那份改了、任一 <xh-config> 改了或进出文档,都走这里。 */
|
|
10
|
+
function notifyXhConfigChange() {
|
|
11
|
+
for (const listener of [...listeners]) listener();
|
|
12
|
+
}
|
|
13
|
+
/** 覆写全局配置。整份替换,不做深合并——想改一处就把整份拿去改。 */
|
|
14
|
+
function setXhConfig(next) {
|
|
15
|
+
current = next;
|
|
16
|
+
applyMotionOverride(next);
|
|
17
|
+
notifyXhConfigChange();
|
|
18
|
+
}
|
|
19
|
+
/** 配置里写了 motion 才调 setMotionOverride;缺席不碰——别的地方设的 override 不在这里清。 */
|
|
20
|
+
function applyMotionOverride(config) {
|
|
21
|
+
if (config.motion !== void 0) setMotionOverride(config.motion);
|
|
22
|
+
}
|
|
23
|
+
function getXhConfig() {
|
|
24
|
+
return current;
|
|
25
|
+
}
|
|
26
|
+
/** 订阅配置变更,返回退订函数。已挂载的元素靠它在切语言时重渲。 */
|
|
27
|
+
function onXhConfigChange(listener) {
|
|
28
|
+
listeners.add(listener);
|
|
29
|
+
return () => void listeners.delete(listener);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 外层与内层逐键合并。
|
|
33
|
+
*
|
|
34
|
+
* 键缺席与写成 undefined 都算「这一层没说」,一律回落外层——子树里只想改文案时,
|
|
35
|
+
* 不该把外层的 locale 一并抹掉。
|
|
36
|
+
*/
|
|
37
|
+
function mergeXhConfig$1(base, over) {
|
|
38
|
+
return mergeXhConfig(base, over);
|
|
39
|
+
}
|
|
40
|
+
function isConfigScope(node) {
|
|
41
|
+
return "xhConfig" in node;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 某个节点看到的配置:从全局那份起,沿祖先链自外向内逐层并进来。
|
|
45
|
+
*
|
|
46
|
+
* 不传节点(或它还没进文档)就只有全局那份。跨 shadow root 不追:
|
|
47
|
+
* 本适配器是 Light DOM,作者的 <xh-config> 与元素天然同树。
|
|
48
|
+
*/
|
|
49
|
+
function resolveXhConfig(node) {
|
|
50
|
+
if (!node) return current;
|
|
51
|
+
const chain = [];
|
|
52
|
+
for (let el = node; el; el = el.parentElement) if (isConfigScope(el)) chain.push(el);
|
|
53
|
+
let out = current;
|
|
54
|
+
for (let i = chain.length - 1; i >= 0; i--) out = mergeXhConfig$1(out, chain[i].xhConfig);
|
|
55
|
+
return out;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 把配置并进一份 props:`translations` 逐键合并、元素上的压过全局;
|
|
59
|
+
* `locale` 与 `size` 在元素上没给(键在但值是 undefined)时取配置里的。
|
|
60
|
+
* 一处都没并到就原样返回,不新建对象。
|
|
61
|
+
*
|
|
62
|
+
* host 是发起解析的元素,给了就沿它的祖先链找 `<xh-config>`;不给只看全局那份。
|
|
63
|
+
*/
|
|
64
|
+
function withXhConfig(component, props, host) {
|
|
65
|
+
return withXhConfigBase(component, props, host === void 0 ? current : resolveXhConfig(host));
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
4
68
|
//#region src/dom/normalize.ts
|
|
5
69
|
const wcNormalize = createNormalizer((props) => props);
|
|
6
70
|
//#endregion
|
|
@@ -240,17 +304,17 @@ function createLitRuntime(host) {
|
|
|
240
304
|
var MachineController = class {
|
|
241
305
|
host;
|
|
242
306
|
machine;
|
|
243
|
-
props;
|
|
244
307
|
opts;
|
|
245
308
|
service;
|
|
246
309
|
runtime;
|
|
247
310
|
started = false;
|
|
248
311
|
formReset;
|
|
312
|
+
props;
|
|
249
313
|
constructor(host, machine, props, opts = {}) {
|
|
250
314
|
this.host = host;
|
|
251
315
|
this.machine = machine;
|
|
252
|
-
this.props = props;
|
|
253
316
|
this.opts = opts;
|
|
317
|
+
this.props = () => withXhConfig(machine.name, props(), host instanceof Element ? host : null);
|
|
254
318
|
host.addController(this);
|
|
255
319
|
}
|
|
256
320
|
build() {
|
|
@@ -292,6 +356,6 @@ var MachineController = class {
|
|
|
292
356
|
}
|
|
293
357
|
};
|
|
294
358
|
//#endregion
|
|
295
|
-
export { containsPart as a, PART_ATTR as i, createLitRuntime as n, discoverParts as o, createSpreader as r, wcNormalize as s, MachineController as t };
|
|
359
|
+
export { containsPart as a, applyMotionOverride as c, notifyXhConfigChange as d, onXhConfigChange as f, withXhConfig as h, PART_ATTR as i, getXhConfig as l, setXhConfig as m, createLitRuntime as n, discoverParts as o, resolveXhConfig as p, createSpreader as r, wcNormalize as s, MachineController as t, mergeXhConfig$1 as u };
|
|
296
360
|
|
|
297
|
-
//# sourceMappingURL=machine-controller-
|
|
361
|
+
//# sourceMappingURL=machine-controller-j_fnUsFq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machine-controller-j_fnUsFq.js","names":["mergeXhConfig","mergeBase"],"sources":["../src/config.ts","../src/dom/normalize.ts","../src/dom/parts.ts","../src/dom/spread.ts","../src/runtime/lit-runtime.ts","../src/runtime/machine-controller.ts"],"sourcesContent":["// 全局配置:locale、尺寸档与各组件内建文案的应用级默认值。\n// 取值优先级:元素上的 property > 最近一个 <xh-config> > 外层 <xh-config> > setXhConfig 的全局值 > 组件内建默认。\n//\n// 自定义元素拿不到 Vue 的 provide/inject,文案又是对象、只能走 property 不能走 attribute。\n// 这里给两条出口:setXhConfig 管整页,<xh-config> 管一棵子树,语义与 Vue 适配器的\n// provideXhConfig 对齐(那边是组件树,这边是 DOM 树)。\nimport type { XhConfigBase, XhTranslationOverrides } from '@xihan-ui/headless'\nimport { mergeXhConfig as mergeBase, withXhConfigBase } from '@xihan-ui/headless'\nimport { setMotionOverride } from '@xihan-ui/motion'\n\nexport type { XhTranslationOverrides }\n\n/** 与 Vue 适配器同一份字段;WC 是 Light DOM,浮层不搬运,没有 portalContainer。 */\nexport type XhConfig = XhConfigBase\n\nlet current: XhConfig = {}\nconst listeners = new Set<() => void>()\n\n/** 配置变了就叫一遍:全局那份改了、任一 <xh-config> 改了或进出文档,都走这里。 */\nexport function notifyXhConfigChange(): void {\n for (const listener of [...listeners]) listener()\n}\n\n/** 覆写全局配置。整份替换,不做深合并——想改一处就把整份拿去改。 */\nexport function setXhConfig(next: XhConfig): void {\n current = next\n applyMotionOverride(next)\n notifyXhConfigChange()\n}\n\n/** 配置里写了 motion 才调 setMotionOverride;缺席不碰——别的地方设的 override 不在这里清。 */\nexport function applyMotionOverride(config: XhConfig): void {\n if (config.motion !== undefined)\n setMotionOverride(config.motion)\n}\n\nexport function getXhConfig(): Readonly<XhConfig> {\n return current\n}\n\n/** 订阅配置变更,返回退订函数。已挂载的元素靠它在切语言时重渲。 */\nexport function onXhConfigChange(listener: () => void): () => void {\n listeners.add(listener)\n return () => void listeners.delete(listener)\n}\n\n/**\n * 外层与内层逐键合并。\n *\n * 键缺席与写成 undefined 都算「这一层没说」,一律回落外层——子树里只想改文案时,\n * 不该把外层的 locale 一并抹掉。\n */\nexport function mergeXhConfig(base: XhConfig | undefined, over: XhConfig | undefined): XhConfig {\n return mergeBase(base, over)\n}\n\n/** `<xh-config>` 认领这个接口,配置解析沿 DOM 祖先链找它,不必反向依赖元素类。 */\nexport interface XhConfigScope extends Element {\n readonly xhConfig: XhConfig\n}\n\nfunction isConfigScope(node: Element): node is XhConfigScope {\n return 'xhConfig' in node\n}\n\n/**\n * 某个节点看到的配置:从全局那份起,沿祖先链自外向内逐层并进来。\n *\n * 不传节点(或它还没进文档)就只有全局那份。跨 shadow root 不追:\n * 本适配器是 Light DOM,作者的 <xh-config> 与元素天然同树。\n */\nexport function resolveXhConfig(node: Element | null | undefined): XhConfig {\n if (!node)\n return current\n const chain: XhConfigScope[] = []\n for (let el: Element | null = node; el; el = el.parentElement) {\n if (isConfigScope(el))\n chain.push(el)\n }\n // 祖先链是自内向外收的,合并要自外向内\n let out = current\n for (let i = chain.length - 1; i >= 0; i--)\n out = mergeXhConfig(out, chain[i]!.xhConfig)\n return out\n}\n\n/**\n * 把配置并进一份 props:`translations` 逐键合并、元素上的压过全局;\n * `locale` 与 `size` 在元素上没给(键在但值是 undefined)时取配置里的。\n * 一处都没并到就原样返回,不新建对象。\n *\n * host 是发起解析的元素,给了就沿它的祖先链找 `<xh-config>`;不给只看全局那份。\n */\nexport function withXhConfig<T extends object>(component: string, props: T, host?: Element | null): T {\n return withXhConfigBase(component, props, host === undefined ? current : resolveXhConfig(host))\n}\n","import { createNormalizer } from '@xihan-ui/kernel'\n\n// connect 产出的键已是 DOM 向,恒等透传,落到真实 DOM 由 spread 完成。\nexport const wcNormalize = createNormalizer(props => props)\n","/** 角色节点标记属性。 */\nexport const PART_ATTR = 'data-xh-part'\n\n/** 元素自身是角色节点,或其子树里有角色节点。 */\nexport function containsPart(el: Element): boolean {\n return el.hasAttribute(PART_ATTR) || el.querySelector(`[${PART_ATTR}]`) != null\n}\n\n// 从宿主向下遍历收集带 data-xh-part 的节点,跳过嵌套 xh-* 子树。\nexport function discoverParts(host: HTMLElement): Map<string, HTMLElement[]> {\n const out = new Map<string, HTMLElement[]>()\n\n function walk(node: Element): void {\n for (const child of Array.from(node.children)) {\n if (child.tagName.toLowerCase().startsWith('xh-'))\n continue\n const el = child as HTMLElement\n const part = el.dataset.xhPart\n if (part) {\n const arr = out.get(part)\n if (arr)\n arr.push(el)\n else\n out.set(part, [el])\n }\n walk(el)\n }\n }\n\n walk(host)\n return out\n}\n","// 把 connect 产出的 prop 字典打到 Light-DOM 角色节点上;事件每帧移旧加新,不碰 class。\n\nconst BOOLEAN_ATTRS = new Set(['disabled', 'hidden', 'inert', 'readonly', 'required', 'checked', 'selected', 'open', 'multiple'])\nconst PROP_KEYS = new Set(['value', 'checked', 'selected'])\n\ninterface NodeState {\n listeners: Map<string, EventListener>\n attrs: Set<string>\n}\n\nfunction eventName(key: string): string | null {\n if (key.length > 2 && key.startsWith('on') && key[2]! >= 'A' && key[2]! <= 'Z')\n return key.slice(2).toLowerCase()\n return null\n}\n\n// 值相同则不写,避免多余的属性变更记录。\nfunction setAttr(node: HTMLElement, key: string, value: string): void {\n if (node.getAttribute(key) !== value)\n node.setAttribute(key, value)\n}\n\nfunction removeAttr(node: HTMLElement, key: string): void {\n if (node.hasAttribute(key))\n node.removeAttribute(key)\n}\n\nexport interface Spreader {\n spread: (node: HTMLElement, props: Record<string, unknown>) => void\n release: (node: HTMLElement) => void\n}\n\n/**\n * 一个角色节点当前归哪台 spreader 管,最后写它的那台就是。\n * 只有仍持有归属的那台交还时才撤属性:两台同类宿主写的属性完全同名,接管后原宿主再撤会把接管方的一起删掉。\n */\nconst owners = new WeakMap<Element, symbol>()\n\nexport function createSpreader(): Spreader {\n const owner = Symbol('spreader')\n const state = new WeakMap<Element, NodeState>()\n\n function spread(node: HTMLElement, props: Record<string, unknown>): void {\n owners.set(node, owner)\n let s = state.get(node)\n if (!s) {\n s = { listeners: new Map(), attrs: new Set() }\n state.set(node, s)\n }\n const nextAttrs = new Set<string>()\n const nextEvents = new Set<string>()\n\n for (const [key, value] of Object.entries(props)) {\n const ev = eventName(key)\n if (ev) {\n nextEvents.add(ev)\n const prev = s.listeners.get(ev)\n if (prev)\n node.removeEventListener(ev, prev)\n if (typeof value === 'function') {\n node.addEventListener(ev, value as EventListener)\n s.listeners.set(ev, value as EventListener)\n }\n else {\n s.listeners.delete(ev)\n }\n continue\n }\n // style 传对象时逐条写内联样式;自定义属性(--开头)走 setProperty,Object.assign 写不进去\n if (key === 'style' && value !== null && typeof value === 'object') {\n for (const [styleKey, styleValue] of Object.entries(value as Record<string, string | undefined>)) {\n if (styleKey.startsWith('--')) {\n if (styleValue == null || styleValue === '')\n node.style.removeProperty(styleKey)\n else\n node.style.setProperty(styleKey, String(styleValue))\n }\n else {\n (node.style as unknown as Record<string, unknown>)[styleKey] = styleValue\n }\n }\n continue\n }\n if (value === undefined || value === null || value === false) {\n removeAttr(node, key)\n continue\n }\n nextAttrs.add(key)\n if (PROP_KEYS.has(key)) {\n (node as unknown as Record<string, unknown>)[key] = value\n continue\n }\n if (BOOLEAN_ATTRS.has(key)) {\n node.toggleAttribute(key, Boolean(value))\n continue\n }\n setAttr(node, key, String(value))\n }\n\n // 移除上一帧写过、这一帧不再写的属性与事件监听器。\n for (const key of s.attrs) {\n if (!nextAttrs.has(key))\n removeAttr(node, key)\n }\n for (const [ev, fn] of [...s.listeners]) {\n if (!nextEvents.has(ev)) {\n node.removeEventListener(ev, fn)\n s.listeners.delete(ev)\n }\n }\n s.attrs = nextAttrs\n }\n\n function release(node: HTMLElement): void {\n const s = state.get(node)\n if (!s)\n return\n for (const [ev, fn] of s.listeners) node.removeEventListener(ev, fn)\n // 节点已被另一台宿主接管时只摘监听器,属性归接管方\n if (owners.get(node) === owner) {\n for (const key of s.attrs) node.removeAttribute(key)\n owners.delete(node)\n }\n state.delete(node)\n }\n\n return { spread, release }\n}\n","import type { Bindable, CellParams, Dep, ReactiveRuntime } from '@xihan-ui/machine'\nimport type { ReactiveControllerHost } from '../reactive'\n\n// 把机器的 ReactiveRuntime 契约桥到自定义元素基类的 controller 生命周期。\n\nexport interface LitRuntime extends ReactiveRuntime {\n /** hostConnected 调用,跑排队的 onMount。 */\n mount: () => void\n /** hostDisconnected 调用,逆序跑一次 cleanup。 */\n unmount: () => void\n /** hostUpdate 调用,逐 tracker 比对依赖、变则触发。 */\n runTrackers: () => void\n}\n\ninterface Tracker {\n deps: Dep[]\n fn: () => void\n last: unknown[]\n}\n\n/** flush 最多等这么多轮更新;宿主一直自排新一轮时到此为止,回调照跑不吊死。 */\nconst MAX_FLUSH_ROUNDS = 100\n\nexport function createLitRuntime(host: ReactiveControllerHost): LitRuntime {\n const mounts: Array<() => void> = []\n const cleanups: Array<() => void> = []\n const trackers: Tracker[] = []\n let mounted = false\n\n function cell<V>(params: () => CellParams<V>): Bindable<V> {\n const p0 = params()\n const eq = p0.isEqual ?? Object.is\n const initial = (p0.defaultValue ?? p0.value) as V\n let inner = initial\n let lastSeen = initial\n let version = 0\n const isControlled = (): boolean => params().value !== undefined\n const read = (): V => (isControlled() ? (params().value as V) : inner)\n const set = (next: V | ((prev: V) => V)): void => {\n const prev = read()\n const value = typeof next === 'function' ? (next as (p: V) => V)(prev) : next\n if (eq(value, prev))\n return\n if (!isControlled())\n inner = value\n params().onChange?.(value, prev)\n host.requestUpdate()\n }\n return {\n initial,\n get: read,\n set,\n // 落点按当下 props 重算,不用挂载时冻结的 initial:宿主换了 defaultValue\n // (比如切去编辑另一条记录)就该回到新的那一份\n reset() {\n const next = params().defaultValue\n if (next === undefined)\n return undefined\n set(next)\n return next\n },\n notify: () => host.requestUpdate(),\n // 版本号按值拉取比对,受控值不经过 set。\n version: () => {\n const cur = read()\n if (!eq(cur, lastSeen)) {\n lastSeen = cur\n version += 1\n }\n return version\n },\n }\n }\n\n return {\n name: 'wc',\n isServer: false,\n cell,\n track(deps, fn) {\n trackers.push({ deps, fn, last: deps.map(d => d()) })\n },\n flush(fn) {\n void (async () => {\n // 先让出一次微任务,等这次转移把宿主的更新排上队,再去读 updateComplete\n await null\n // updateComplete resolve 成 false 表示更新途中又排了新一轮,DOM 还没落定,接着等下一轮。\n let rounds = 0\n while (!(await host.updateComplete) && rounds < MAX_FLUSH_ROUNDS)\n rounds += 1\n fn()\n })()\n },\n onMount(fn) {\n mounts.push(fn)\n if (mounted)\n fn()\n },\n onCleanup(fn) {\n cleanups.push(fn)\n },\n mount() {\n if (mounted)\n return\n mounted = true\n for (const fn of mounts) fn()\n },\n unmount() {\n if (!mounted)\n return\n mounted = false\n for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]!()\n cleanups.length = 0\n },\n runTrackers() {\n let errors: unknown[] | undefined\n for (const t of trackers) {\n const next = t.deps.map(d => d())\n if (!next.some((v, i) => !Object.is(v, t.last[i])))\n continue\n const prev = t.last\n // 跑之前先推进:fn 内部若又进到 runTrackers,不会拿同一次变化再触发一遍。\n t.last = next\n try {\n t.fn()\n }\n catch (error) {\n // 回滚到未消费,这次变化留给下一轮补跑;错误攒着,先把余下 tracker 跑完。\n t.last = prev\n errors ??= []\n errors.push(error)\n }\n }\n if (errors !== undefined)\n throw errors.length === 1 ? errors[0] : new AggregateError(errors, 'tracker 抛错')\n },\n }\n}\n","import type { Disposable, Scope } from '@xihan-ui/kernel'\nimport type { MachineConfig, MachineSchema, Service } from '@xihan-ui/machine'\nimport type { ReactiveController, ReactiveControllerHost } from '../reactive'\nimport type { LitRuntime } from './lit-runtime'\nimport { createFormResetBridge } from '@xihan-ui/behavior'\nimport { createService, declaresFormReset, FORM_RESET_EVENT } from '@xihan-ui/machine'\nimport { withXhConfig } from '../config'\n\nimport { createLitRuntime } from './lit-runtime'\n\nexport interface MachineControllerOptions<T extends MachineSchema> {\n scope?: Scope\n /** 每次建机器后回调,用于注入 refs。 */\n onBuilt?: (service: Service<T>) => void\n}\n\n// 一台机器一个 controller:hostConnected 建机器并 mount、hostUpdate 跑 trackers、hostDisconnected unmount。\nexport class MachineController<T extends MachineSchema> implements ReactiveController {\n service!: Service<T>\n private runtime: LitRuntime | undefined\n private started = false\n private formReset: Disposable | undefined\n\n private readonly props: () => Partial<T['props']>\n\n constructor(\n private readonly host: ReactiveControllerHost,\n private readonly machine: MachineConfig<T>,\n props: () => Partial<T['props']>,\n private readonly opts: MachineControllerOptions<T> = {},\n ) {\n // 全局配置在这一处并进来:所有跑机器的元素都从这里取 props,不必逐个接线。\n // 传宿主元素而不是只看全局那份:配置沿 DOM 祖先链解析,作者用 <xh-config> 包住一棵子树即可局部覆盖\n this.props = () => withXhConfig(machine.name, props(), host instanceof Element ? host : null)\n host.addController(this)\n // 延到 hostConnected 再 build,构造期 attribute 尚未反射到 reactive property。\n }\n\n private build(): void {\n this.runtime = createLitRuntime(this.host)\n this.service = createService(this.machine, { props: this.props, runtime: this.runtime, scope: this.opts.scope })\n this.opts.onBuilt?.(this.service)\n }\n\n hostConnected(): void {\n // 首次或旧机器已停止时重建,从 initialState 起。\n if (!this.started || this.service.getStatus() === 'Stopped') {\n this.build()\n this.started = true\n }\n this.runtime!.mount()\n // 必须在 mount 之后:桥一挂就可能送事件进来,而 mount 之前送会撞上 SEND_BEFORE_MOUNT\n this.attachFormReset()\n }\n\n /** 元素自己就是锚点(Light DOM)。重连时重建,指向新那台机器。 */\n private attachFormReset(): void {\n if (this.formReset || !declaresFormReset(this.machine))\n return\n const host = this.host as unknown\n if (!(host instanceof Element))\n return\n this.formReset = createFormResetBridge({\n getNode: () => host,\n onReset: () => {\n if (this.service.getStatus() === 'Started')\n this.service.send({ type: FORM_RESET_EVENT } as T['event'])\n },\n })\n }\n\n hostUpdate(): void {\n this.runtime?.runTrackers()\n }\n\n hostDisconnected(): void {\n this.formReset?.dispose()\n this.formReset = undefined\n this.runtime?.unmount()\n }\n}\n"],"mappings":";;;;;;AAeA,IAAI,UAAoB,CAAC;AACzB,MAAM,4BAAY,IAAI,IAAgB;;AAGtC,SAAgB,uBAA6B;CAC3C,KAAK,MAAM,YAAY,CAAC,GAAG,SAAS,GAAG,SAAS;AAClD;;AAGA,SAAgB,YAAY,MAAsB;CAChD,UAAU;CACV,oBAAoB,IAAI;CACxB,qBAAqB;AACvB;;AAGA,SAAgB,oBAAoB,QAAwB;CAC1D,IAAI,OAAO,WAAW,KAAA,GACpB,kBAAkB,OAAO,MAAM;AACnC;AAEA,SAAgB,cAAkC;CAChD,OAAO;AACT;;AAGA,SAAgB,iBAAiB,UAAkC;CACjE,UAAU,IAAI,QAAQ;CACtB,aAAa,KAAK,UAAU,OAAO,QAAQ;AAC7C;;;;;;;AAQA,SAAgBA,gBAAc,MAA4B,MAAsC;CAC9F,OAAOC,cAAU,MAAM,IAAI;AAC7B;AAOA,SAAS,cAAc,MAAsC;CAC3D,OAAO,cAAc;AACvB;;;;;;;AAQA,SAAgB,gBAAgB,MAA4C;CAC1E,IAAI,CAAC,MACH,OAAO;CACT,MAAM,QAAyB,CAAC;CAChC,KAAK,IAAI,KAAqB,MAAM,IAAI,KAAK,GAAG,eAC9C,IAAI,cAAc,EAAE,GAClB,MAAM,KAAK,EAAE;CAGjB,IAAI,MAAM;CACV,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KACrC,MAAMD,gBAAc,KAAK,MAAM,EAAE,CAAE,QAAQ;CAC7C,OAAO;AACT;;;;;;;;AASA,SAAgB,aAA+B,WAAmB,OAAU,MAA0B;CACpG,OAAO,iBAAiB,WAAW,OAAO,SAAS,KAAA,IAAY,UAAU,gBAAgB,IAAI,CAAC;AAChG;;;AC5FA,MAAa,cAAc,kBAAiB,UAAS,KAAK;;;;ACF1D,MAAa,YAAY;;AAGzB,SAAgB,aAAa,IAAsB;CACjD,OAAO,GAAG,aAAA,cAAsB,KAAK,GAAG,cAAc,gBAAgB,KAAK;AAC7E;AAGA,SAAgB,cAAc,MAA+C;CAC3E,MAAM,sBAAM,IAAI,IAA2B;CAE3C,SAAS,KAAK,MAAqB;EACjC,KAAK,MAAM,SAAS,MAAM,KAAK,KAAK,QAAQ,GAAG;GAC7C,IAAI,MAAM,QAAQ,YAAY,CAAC,CAAC,WAAW,KAAK,GAC9C;GACF,MAAM,KAAK;GACX,MAAM,OAAO,GAAG,QAAQ;GACxB,IAAI,MAAM;IACR,MAAM,MAAM,IAAI,IAAI,IAAI;IACxB,IAAI,KACF,IAAI,KAAK,EAAE;SAEX,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC;GACtB;GACA,KAAK,EAAE;EACT;CACF;CAEA,KAAK,IAAI;CACT,OAAO;AACT;;;AC7BA,MAAM,gCAAgB,IAAI,IAAI;CAAC;CAAY;CAAU;CAAS;CAAY;CAAY;CAAW;CAAY;CAAQ;AAAU,CAAC;AAChI,MAAM,4BAAY,IAAI,IAAI;CAAC;CAAS;CAAW;AAAU,CAAC;AAO1D,SAAS,UAAU,KAA4B;CAC7C,IAAI,IAAI,SAAS,KAAK,IAAI,WAAW,IAAI,KAAK,IAAI,MAAO,OAAO,IAAI,MAAO,KACzE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,YAAY;CAClC,OAAO;AACT;AAGA,SAAS,QAAQ,MAAmB,KAAa,OAAqB;CACpE,IAAI,KAAK,aAAa,GAAG,MAAM,OAC7B,KAAK,aAAa,KAAK,KAAK;AAChC;AAEA,SAAS,WAAW,MAAmB,KAAmB;CACxD,IAAI,KAAK,aAAa,GAAG,GACvB,KAAK,gBAAgB,GAAG;AAC5B;;;;;AAWA,MAAM,yBAAS,IAAI,QAAyB;AAE5C,SAAgB,iBAA2B;CACzC,MAAM,QAAQ,OAAO,UAAU;CAC/B,MAAM,wBAAQ,IAAI,QAA4B;CAE9C,SAAS,OAAO,MAAmB,OAAsC;EACvE,OAAO,IAAI,MAAM,KAAK;EACtB,IAAI,IAAI,MAAM,IAAI,IAAI;EACtB,IAAI,CAAC,GAAG;GACN,IAAI;IAAE,2BAAW,IAAI,IAAI;IAAG,uBAAO,IAAI,IAAI;GAAE;GAC7C,MAAM,IAAI,MAAM,CAAC;EACnB;EACA,MAAM,4BAAY,IAAI,IAAY;EAClC,MAAM,6BAAa,IAAI,IAAY;EAEnC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;GAChD,MAAM,KAAK,UAAU,GAAG;GACxB,IAAI,IAAI;IACN,WAAW,IAAI,EAAE;IACjB,MAAM,OAAO,EAAE,UAAU,IAAI,EAAE;IAC/B,IAAI,MACF,KAAK,oBAAoB,IAAI,IAAI;IACnC,IAAI,OAAO,UAAU,YAAY;KAC/B,KAAK,iBAAiB,IAAI,KAAsB;KAChD,EAAE,UAAU,IAAI,IAAI,KAAsB;IAC5C,OAEE,EAAE,UAAU,OAAO,EAAE;IAEvB;GACF;GAEA,IAAI,QAAQ,WAAW,UAAU,QAAQ,OAAO,UAAU,UAAU;IAClE,KAAK,MAAM,CAAC,UAAU,eAAe,OAAO,QAAQ,KAA2C,GAC7F,IAAI,SAAS,WAAW,IAAI,GAC1B,IAAI,cAAc,QAAQ,eAAe,IACvC,KAAK,MAAM,eAAe,QAAQ;SAElC,KAAK,MAAM,YAAY,UAAU,OAAO,UAAU,CAAC;SAGrD,KAAM,MAA6C,YAAY;IAGnE;GACF;GACA,IAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,OAAO;IAC5D,WAAW,MAAM,GAAG;IACpB;GACF;GACA,UAAU,IAAI,GAAG;GACjB,IAAI,UAAU,IAAI,GAAG,GAAG;IACtB,KAA6C,OAAO;IACpD;GACF;GACA,IAAI,cAAc,IAAI,GAAG,GAAG;IAC1B,KAAK,gBAAgB,KAAK,QAAQ,KAAK,CAAC;IACxC;GACF;GACA,QAAQ,MAAM,KAAK,OAAO,KAAK,CAAC;EAClC;EAGA,KAAK,MAAM,OAAO,EAAE,OAClB,IAAI,CAAC,UAAU,IAAI,GAAG,GACpB,WAAW,MAAM,GAAG;EAExB,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,SAAS,GACpC,IAAI,CAAC,WAAW,IAAI,EAAE,GAAG;GACvB,KAAK,oBAAoB,IAAI,EAAE;GAC/B,EAAE,UAAU,OAAO,EAAE;EACvB;EAEF,EAAE,QAAQ;CACZ;CAEA,SAAS,QAAQ,MAAyB;EACxC,MAAM,IAAI,MAAM,IAAI,IAAI;EACxB,IAAI,CAAC,GACH;EACF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,WAAW,KAAK,oBAAoB,IAAI,EAAE;EAEnE,IAAI,OAAO,IAAI,IAAI,MAAM,OAAO;GAC9B,KAAK,MAAM,OAAO,EAAE,OAAO,KAAK,gBAAgB,GAAG;GACnD,OAAO,OAAO,IAAI;EACpB;EACA,MAAM,OAAO,IAAI;CACnB;CAEA,OAAO;EAAE;EAAQ;CAAQ;AAC3B;;;;AC1GA,MAAM,mBAAmB;AAEzB,SAAgB,iBAAiB,MAA0C;CACzE,MAAM,SAA4B,CAAC;CACnC,MAAM,WAA8B,CAAC;CACrC,MAAM,WAAsB,CAAC;CAC7B,IAAI,UAAU;CAEd,SAAS,KAAQ,QAA0C;EACzD,MAAM,KAAK,OAAO;EAClB,MAAM,KAAK,GAAG,WAAW,OAAO;EAChC,MAAM,UAAW,GAAG,gBAAgB,GAAG;EACvC,IAAI,QAAQ;EACZ,IAAI,WAAW;EACf,IAAI,UAAU;EACd,MAAM,qBAA8B,OAAO,CAAC,CAAC,UAAU,KAAA;EACvD,MAAM,aAAiB,aAAa,IAAK,OAAO,CAAC,CAAC,QAAc;EAChE,MAAM,OAAO,SAAqC;GAChD,MAAM,OAAO,KAAK;GAClB,MAAM,QAAQ,OAAO,SAAS,aAAc,KAAqB,IAAI,IAAI;GACzE,IAAI,GAAG,OAAO,IAAI,GAChB;GACF,IAAI,CAAC,aAAa,GAChB,QAAQ;GACV,OAAO,CAAC,CAAC,WAAW,OAAO,IAAI;GAC/B,KAAK,cAAc;EACrB;EACA,OAAO;GACL;GACA,KAAK;GACL;GAGA,QAAQ;IACN,MAAM,OAAO,OAAO,CAAC,CAAC;IACtB,IAAI,SAAS,KAAA,GACX,OAAO,KAAA;IACT,IAAI,IAAI;IACR,OAAO;GACT;GACA,cAAc,KAAK,cAAc;GAEjC,eAAe;IACb,MAAM,MAAM,KAAK;IACjB,IAAI,CAAC,GAAG,KAAK,QAAQ,GAAG;KACtB,WAAW;KACX,WAAW;IACb;IACA,OAAO;GACT;EACF;CACF;CAEA,OAAO;EACL,MAAM;EACN,UAAU;EACV;EACA,MAAM,MAAM,IAAI;GACd,SAAS,KAAK;IAAE;IAAM;IAAI,MAAM,KAAK,KAAI,MAAK,EAAE,CAAC;GAAE,CAAC;EACtD;EACA,MAAM,IAAI;GACR,CAAM,YAAY;IAEhB,MAAM;IAEN,IAAI,SAAS;IACb,OAAO,CAAE,MAAM,KAAK,kBAAmB,SAAS,kBAC9C,UAAU;IACZ,GAAG;GACL,EAAA,CAAG;EACL;EACA,QAAQ,IAAI;GACV,OAAO,KAAK,EAAE;GACd,IAAI,SACF,GAAG;EACP;EACA,UAAU,IAAI;GACZ,SAAS,KAAK,EAAE;EAClB;EACA,QAAQ;GACN,IAAI,SACF;GACF,UAAU;GACV,KAAK,MAAM,MAAM,QAAQ,GAAG;EAC9B;EACA,UAAU;GACR,IAAI,CAAC,SACH;GACF,UAAU;GACV,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK,SAAS,EAAE,CAAE;GAC5D,SAAS,SAAS;EACpB;EACA,cAAc;GACZ,IAAI;GACJ,KAAK,MAAM,KAAK,UAAU;IACxB,MAAM,OAAO,EAAE,KAAK,KAAI,MAAK,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,MAAM,GAAG,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,KAAK,EAAE,CAAC,GAC/C;IACF,MAAM,OAAO,EAAE;IAEf,EAAE,OAAO;IACT,IAAI;KACF,EAAE,GAAG;IACP,SACO,OAAO;KAEZ,EAAE,OAAO;KACT,WAAW,CAAC;KACZ,OAAO,KAAK,KAAK;IACnB;GACF;GACA,IAAI,WAAW,KAAA,GACb,MAAM,OAAO,WAAW,IAAI,OAAO,KAAK,IAAI,eAAe,QAAQ,YAAY;EACnF;CACF;AACF;;;ACvHA,IAAa,oBAAb,MAAsF;CASjE;CACA;CAEA;CAXnB;CACA;CACA,UAAkB;CAClB;CAEA;CAEA,YACE,MACA,SACA,OACA,OAAqD,CAAC,GACtD;EAJiB,KAAA,OAAA;EACA,KAAA,UAAA;EAEA,KAAA,OAAA;EAIjB,KAAK,cAAc,aAAa,QAAQ,MAAM,MAAM,GAAG,gBAAgB,UAAU,OAAO,IAAI;EAC5F,KAAK,cAAc,IAAI;CAEzB;CAEA,QAAsB;EACpB,KAAK,UAAU,iBAAiB,KAAK,IAAI;EACzC,KAAK,UAAU,cAAc,KAAK,SAAS;GAAE,OAAO,KAAK;GAAO,SAAS,KAAK;GAAS,OAAO,KAAK,KAAK;EAAM,CAAC;EAC/G,KAAK,KAAK,UAAU,KAAK,OAAO;CAClC;CAEA,gBAAsB;EAEpB,IAAI,CAAC,KAAK,WAAW,KAAK,QAAQ,UAAU,MAAM,WAAW;GAC3D,KAAK,MAAM;GACX,KAAK,UAAU;EACjB;EACA,KAAK,QAAS,MAAM;EAEpB,KAAK,gBAAgB;CACvB;;CAGA,kBAAgC;EAC9B,IAAI,KAAK,aAAa,CAAC,kBAAkB,KAAK,OAAO,GACnD;EACF,MAAM,OAAO,KAAK;EAClB,IAAI,EAAE,gBAAgB,UACpB;EACF,KAAK,YAAY,sBAAsB;GACrC,eAAe;GACf,eAAe;IACb,IAAI,KAAK,QAAQ,UAAU,MAAM,WAC/B,KAAK,QAAQ,KAAK,EAAE,MAAM,iBAAiB,CAAe;GAC9D;EACF,CAAC;CACH;CAEA,aAAmB;EACjB,KAAK,SAAS,YAAY;CAC5B;CAEA,mBAAyB;EACvB,KAAK,WAAW,QAAQ;EACxB,KAAK,YAAY,KAAA;EACjB,KAAK,SAAS,QAAQ;CACxB;AACF"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xihan-ui/web-components",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-alpha.
|
|
4
|
+
"version": "1.0.0-alpha.3",
|
|
5
5
|
"description": "XiHan.UI Web Components adapter — Light-DOM behavior hosts on XhReactiveElement.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "XiHanFun",
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
"types": "./dist/index.d.ts",
|
|
30
30
|
"import": "./dist/index.js"
|
|
31
31
|
},
|
|
32
|
-
"./define": {
|
|
33
|
-
"types": "./dist/define.d.ts",
|
|
34
|
-
"import": "./dist/define.js"
|
|
35
|
-
},
|
|
36
32
|
"./backgrounds": {
|
|
37
33
|
"types": "./dist/backgrounds.d.ts",
|
|
38
34
|
"import": "./dist/backgrounds.js"
|
|
39
35
|
},
|
|
36
|
+
"./define": {
|
|
37
|
+
"types": "./dist/define.d.ts",
|
|
38
|
+
"import": "./dist/define.js"
|
|
39
|
+
},
|
|
40
40
|
"./custom-elements.json": "./custom-elements.json"
|
|
41
41
|
},
|
|
42
42
|
"main": "./dist/index.js",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"customElements": "custom-elements.json",
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@xihan-ui/backgrounds": "^1.0.0-alpha.
|
|
59
|
+
"@xihan-ui/backgrounds": "^1.0.0-alpha.3"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"@xihan-ui/backgrounds": {
|
|
@@ -64,12 +64,13 @@
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@xihan-ui/behavior": "^1.0.0-alpha.
|
|
68
|
-
"@xihan-ui/code-highlight": "^1.0.0-alpha.
|
|
69
|
-
"@xihan-ui/headless": "^1.0.0-alpha.
|
|
70
|
-
"@xihan-ui/kernel": "^1.0.0-alpha.
|
|
71
|
-
"@xihan-ui/machine": "^1.0.0-alpha.
|
|
72
|
-
"@xihan-ui/
|
|
67
|
+
"@xihan-ui/behavior": "^1.0.0-alpha.3",
|
|
68
|
+
"@xihan-ui/code-highlight": "^1.0.0-alpha.3",
|
|
69
|
+
"@xihan-ui/headless": "^1.0.0-alpha.3",
|
|
70
|
+
"@xihan-ui/kernel": "^1.0.0-alpha.3",
|
|
71
|
+
"@xihan-ui/machine": "^1.0.0-alpha.3",
|
|
72
|
+
"@xihan-ui/motion": "^1.0.0-alpha.3",
|
|
73
|
+
"@xihan-ui/position": "^1.0.0-alpha.3"
|
|
73
74
|
},
|
|
74
75
|
"devDependencies": {
|
|
75
76
|
"@custom-elements-manifest/analyzer": "^0.11.0",
|
|
@@ -79,18 +80,19 @@
|
|
|
79
80
|
"jsdom": "^27.0.0",
|
|
80
81
|
"playwright": "^1.62.0",
|
|
81
82
|
"vitest": "^4.1.10",
|
|
82
|
-
"@xihan-ui/backgrounds": "1.0.0-alpha.
|
|
83
|
+
"@xihan-ui/backgrounds": "1.0.0-alpha.3",
|
|
83
84
|
"@xihan-ui/build": "0.0.0",
|
|
84
|
-
"@xihan-ui/styles": "1.0.0-alpha.
|
|
85
|
+
"@xihan-ui/styles": "1.0.0-alpha.3",
|
|
85
86
|
"@xihan-ui/testing": "0.0.0",
|
|
86
|
-
"@xihan-ui/tokens": "1.0.0-alpha.
|
|
87
|
+
"@xihan-ui/tokens": "1.0.0-alpha.3",
|
|
87
88
|
"@xihan-ui/tsconfig": "0.0.0"
|
|
88
89
|
},
|
|
89
90
|
"scripts": {
|
|
90
91
|
"build": "tsdown",
|
|
91
|
-
"cem": "cem analyze",
|
|
92
|
+
"cem": "cem analyze && node scripts/enrich-cem.mjs",
|
|
92
93
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
93
94
|
"test": "vitest run",
|
|
94
|
-
"test:browser": "vitest run --config vitest.browser.config.ts"
|
|
95
|
+
"test:browser": "vitest run --config vitest.browser.config.ts",
|
|
96
|
+
"test:demos": "vitest run --config vitest.demos.config.ts --reporter verbose"
|
|
95
97
|
}
|
|
96
98
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"machine-controller-Cq9t_cfJ.js","names":[],"sources":["../src/dom/normalize.ts","../src/dom/parts.ts","../src/dom/spread.ts","../src/runtime/lit-runtime.ts","../src/runtime/machine-controller.ts"],"sourcesContent":["import { createNormalizer } from '@xihan-ui/kernel'\n\n// connect 产出的键已是 DOM 向,恒等透传,落到真实 DOM 由 spread 完成。\nexport const wcNormalize = createNormalizer(props => props)\n","/** 角色节点标记属性。 */\nexport const PART_ATTR = 'data-xh-part'\n\n/** 元素自身是角色节点,或其子树里有角色节点。 */\nexport function containsPart(el: Element): boolean {\n return el.hasAttribute(PART_ATTR) || el.querySelector(`[${PART_ATTR}]`) != null\n}\n\n// 从宿主向下遍历收集带 data-xh-part 的节点,跳过嵌套 xh-* 子树。\nexport function discoverParts(host: HTMLElement): Map<string, HTMLElement[]> {\n const out = new Map<string, HTMLElement[]>()\n\n function walk(node: Element): void {\n for (const child of Array.from(node.children)) {\n if (child.tagName.toLowerCase().startsWith('xh-'))\n continue\n const el = child as HTMLElement\n const part = el.dataset.xhPart\n if (part) {\n const arr = out.get(part)\n if (arr)\n arr.push(el)\n else\n out.set(part, [el])\n }\n walk(el)\n }\n }\n\n walk(host)\n return out\n}\n","// 把 connect 产出的 prop 字典打到 Light-DOM 角色节点上;事件每帧移旧加新,不碰 class。\n\nconst BOOLEAN_ATTRS = new Set(['disabled', 'hidden', 'inert', 'readonly', 'required', 'checked', 'selected', 'open', 'multiple'])\nconst PROP_KEYS = new Set(['value', 'checked', 'selected'])\n\ninterface NodeState {\n listeners: Map<string, EventListener>\n attrs: Set<string>\n}\n\nfunction eventName(key: string): string | null {\n if (key.length > 2 && key.startsWith('on') && key[2]! >= 'A' && key[2]! <= 'Z')\n return key.slice(2).toLowerCase()\n return null\n}\n\n// 值相同则不写,避免多余的属性变更记录。\nfunction setAttr(node: HTMLElement, key: string, value: string): void {\n if (node.getAttribute(key) !== value)\n node.setAttribute(key, value)\n}\n\nfunction removeAttr(node: HTMLElement, key: string): void {\n if (node.hasAttribute(key))\n node.removeAttribute(key)\n}\n\nexport interface Spreader {\n spread: (node: HTMLElement, props: Record<string, unknown>) => void\n release: (node: HTMLElement) => void\n}\n\n/**\n * 一个角色节点当前归哪台 spreader 管,最后写它的那台就是。\n * 只有仍持有归属的那台交还时才撤属性:两台同类宿主写的属性完全同名,接管后原宿主再撤会把接管方的一起删掉。\n */\nconst owners = new WeakMap<Element, symbol>()\n\nexport function createSpreader(): Spreader {\n const owner = Symbol('spreader')\n const state = new WeakMap<Element, NodeState>()\n\n function spread(node: HTMLElement, props: Record<string, unknown>): void {\n owners.set(node, owner)\n let s = state.get(node)\n if (!s) {\n s = { listeners: new Map(), attrs: new Set() }\n state.set(node, s)\n }\n const nextAttrs = new Set<string>()\n const nextEvents = new Set<string>()\n\n for (const [key, value] of Object.entries(props)) {\n const ev = eventName(key)\n if (ev) {\n nextEvents.add(ev)\n const prev = s.listeners.get(ev)\n if (prev)\n node.removeEventListener(ev, prev)\n if (typeof value === 'function') {\n node.addEventListener(ev, value as EventListener)\n s.listeners.set(ev, value as EventListener)\n }\n else {\n s.listeners.delete(ev)\n }\n continue\n }\n // style 传对象时逐条写内联样式;自定义属性(--开头)走 setProperty,Object.assign 写不进去\n if (key === 'style' && value !== null && typeof value === 'object') {\n for (const [styleKey, styleValue] of Object.entries(value as Record<string, string | undefined>)) {\n if (styleKey.startsWith('--')) {\n if (styleValue == null || styleValue === '')\n node.style.removeProperty(styleKey)\n else\n node.style.setProperty(styleKey, String(styleValue))\n }\n else {\n (node.style as unknown as Record<string, unknown>)[styleKey] = styleValue\n }\n }\n continue\n }\n if (value === undefined || value === null || value === false) {\n removeAttr(node, key)\n continue\n }\n nextAttrs.add(key)\n if (PROP_KEYS.has(key)) {\n (node as unknown as Record<string, unknown>)[key] = value\n continue\n }\n if (BOOLEAN_ATTRS.has(key)) {\n node.toggleAttribute(key, Boolean(value))\n continue\n }\n setAttr(node, key, String(value))\n }\n\n // 移除上一帧写过、这一帧不再写的属性与事件监听器。\n for (const key of s.attrs) {\n if (!nextAttrs.has(key))\n removeAttr(node, key)\n }\n for (const [ev, fn] of [...s.listeners]) {\n if (!nextEvents.has(ev)) {\n node.removeEventListener(ev, fn)\n s.listeners.delete(ev)\n }\n }\n s.attrs = nextAttrs\n }\n\n function release(node: HTMLElement): void {\n const s = state.get(node)\n if (!s)\n return\n for (const [ev, fn] of s.listeners) node.removeEventListener(ev, fn)\n // 节点已被另一台宿主接管时只摘监听器,属性归接管方\n if (owners.get(node) === owner) {\n for (const key of s.attrs) node.removeAttribute(key)\n owners.delete(node)\n }\n state.delete(node)\n }\n\n return { spread, release }\n}\n","import type { Bindable, CellParams, Dep, ReactiveRuntime } from '@xihan-ui/machine'\nimport type { ReactiveControllerHost } from '../reactive'\n\n// 把机器的 ReactiveRuntime 契约桥到自定义元素基类的 controller 生命周期。\n\nexport interface LitRuntime extends ReactiveRuntime {\n /** hostConnected 调用,跑排队的 onMount。 */\n mount: () => void\n /** hostDisconnected 调用,逆序跑一次 cleanup。 */\n unmount: () => void\n /** hostUpdate 调用,逐 tracker 比对依赖、变则触发。 */\n runTrackers: () => void\n}\n\ninterface Tracker {\n deps: Dep[]\n fn: () => void\n last: unknown[]\n}\n\n/** flush 最多等这么多轮更新;宿主一直自排新一轮时到此为止,回调照跑不吊死。 */\nconst MAX_FLUSH_ROUNDS = 100\n\nexport function createLitRuntime(host: ReactiveControllerHost): LitRuntime {\n const mounts: Array<() => void> = []\n const cleanups: Array<() => void> = []\n const trackers: Tracker[] = []\n let mounted = false\n\n function cell<V>(params: () => CellParams<V>): Bindable<V> {\n const p0 = params()\n const eq = p0.isEqual ?? Object.is\n const initial = (p0.defaultValue ?? p0.value) as V\n let inner = initial\n let lastSeen = initial\n let version = 0\n const isControlled = (): boolean => params().value !== undefined\n const read = (): V => (isControlled() ? (params().value as V) : inner)\n const set = (next: V | ((prev: V) => V)): void => {\n const prev = read()\n const value = typeof next === 'function' ? (next as (p: V) => V)(prev) : next\n if (eq(value, prev))\n return\n if (!isControlled())\n inner = value\n params().onChange?.(value, prev)\n host.requestUpdate()\n }\n return {\n initial,\n get: read,\n set,\n // 落点按当下 props 重算,不用挂载时冻结的 initial:宿主换了 defaultValue\n // (比如切去编辑另一条记录)就该回到新的那一份\n reset() {\n const next = params().defaultValue\n if (next === undefined)\n return undefined\n set(next)\n return next\n },\n notify: () => host.requestUpdate(),\n // 版本号按值拉取比对,受控值不经过 set。\n version: () => {\n const cur = read()\n if (!eq(cur, lastSeen)) {\n lastSeen = cur\n version += 1\n }\n return version\n },\n }\n }\n\n return {\n name: 'wc',\n isServer: false,\n cell,\n track(deps, fn) {\n trackers.push({ deps, fn, last: deps.map(d => d()) })\n },\n flush(fn) {\n void (async () => {\n // 先让出一次微任务,等这次转移把宿主的更新排上队,再去读 updateComplete\n await null\n // updateComplete resolve 成 false 表示更新途中又排了新一轮,DOM 还没落定,接着等下一轮。\n let rounds = 0\n while (!(await host.updateComplete) && rounds < MAX_FLUSH_ROUNDS)\n rounds += 1\n fn()\n })()\n },\n onMount(fn) {\n mounts.push(fn)\n if (mounted)\n fn()\n },\n onCleanup(fn) {\n cleanups.push(fn)\n },\n mount() {\n if (mounted)\n return\n mounted = true\n for (const fn of mounts) fn()\n },\n unmount() {\n if (!mounted)\n return\n mounted = false\n for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]!()\n cleanups.length = 0\n },\n runTrackers() {\n let errors: unknown[] | undefined\n for (const t of trackers) {\n const next = t.deps.map(d => d())\n if (!next.some((v, i) => !Object.is(v, t.last[i])))\n continue\n const prev = t.last\n // 跑之前先推进:fn 内部若又进到 runTrackers,不会拿同一次变化再触发一遍。\n t.last = next\n try {\n t.fn()\n }\n catch (error) {\n // 回滚到未消费,这次变化留给下一轮补跑;错误攒着,先把余下 tracker 跑完。\n t.last = prev\n errors ??= []\n errors.push(error)\n }\n }\n if (errors !== undefined)\n throw errors.length === 1 ? errors[0] : new AggregateError(errors, 'tracker 抛错')\n },\n }\n}\n","import type { Disposable, Scope } from '@xihan-ui/kernel'\nimport type { MachineConfig, MachineSchema, Service } from '@xihan-ui/machine'\nimport type { ReactiveController, ReactiveControllerHost } from '../reactive'\nimport type { LitRuntime } from './lit-runtime'\nimport { createFormResetBridge } from '@xihan-ui/behavior'\nimport { createService, declaresFormReset, FORM_RESET_EVENT } from '@xihan-ui/machine'\nimport { createLitRuntime } from './lit-runtime'\n\nexport interface MachineControllerOptions<T extends MachineSchema> {\n scope?: Scope\n /** 每次建机器后回调,用于注入 refs。 */\n onBuilt?: (service: Service<T>) => void\n}\n\n// 一台机器一个 controller:hostConnected 建机器并 mount、hostUpdate 跑 trackers、hostDisconnected unmount。\nexport class MachineController<T extends MachineSchema> implements ReactiveController {\n service!: Service<T>\n private runtime: LitRuntime | undefined\n private started = false\n private formReset: Disposable | undefined\n\n constructor(\n private readonly host: ReactiveControllerHost,\n private readonly machine: MachineConfig<T>,\n private readonly props: () => Partial<T['props']>,\n private readonly opts: MachineControllerOptions<T> = {},\n ) {\n host.addController(this)\n // 延到 hostConnected 再 build,构造期 attribute 尚未反射到 reactive property。\n }\n\n private build(): void {\n this.runtime = createLitRuntime(this.host)\n this.service = createService(this.machine, { props: this.props, runtime: this.runtime, scope: this.opts.scope })\n this.opts.onBuilt?.(this.service)\n }\n\n hostConnected(): void {\n // 首次或旧机器已停止时重建,从 initialState 起。\n if (!this.started || this.service.getStatus() === 'Stopped') {\n this.build()\n this.started = true\n }\n this.runtime!.mount()\n // 必须在 mount 之后:桥一挂就可能送事件进来,而 mount 之前送会撞上 SEND_BEFORE_MOUNT\n this.attachFormReset()\n }\n\n /** 元素自己就是锚点(Light DOM)。重连时重建,指向新那台机器。 */\n private attachFormReset(): void {\n if (this.formReset || !declaresFormReset(this.machine))\n return\n const host = this.host as unknown\n if (!(host instanceof Element))\n return\n this.formReset = createFormResetBridge({\n getNode: () => host,\n onReset: () => {\n if (this.service.getStatus() === 'Started')\n this.service.send({ type: FORM_RESET_EVENT } as T['event'])\n },\n })\n }\n\n hostUpdate(): void {\n this.runtime?.runTrackers()\n }\n\n hostDisconnected(): void {\n this.formReset?.dispose()\n this.formReset = undefined\n this.runtime?.unmount()\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region src/dom/spread.d.ts
|
|
2
|
-
interface Spreader {
|
|
3
|
-
spread: (node: HTMLElement, props: Record<string, unknown>) => void;
|
|
4
|
-
release: (node: HTMLElement) => void;
|
|
5
|
-
}
|
|
6
|
-
declare function createSpreader(): Spreader;
|
|
7
|
-
//#endregion
|
|
8
|
-
export { createSpreader as n, Spreader as t };
|
|
9
|
-
//# sourceMappingURL=spread-Ch8ZXZDC.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"spread-Ch8ZXZDC.d.ts","names":[],"sources":["../src/dom/spread.ts"],"mappings":";UA2BiB;EACf,SAAS,MAAM,aAAa,OAAO;EACnC,UAAU,MAAM;;iBASF,kBAAkB"}
|