@yahoo/uds-create-config 2.45.0 → 3.0.0

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.
Files changed (376) hide show
  1. package/README.md +129 -0
  2. package/dist/ai-lanes.d.ts +23 -0
  3. package/dist/ai-lanes.js +34 -0
  4. package/dist/authoring/define-component.d.ts +85 -0
  5. package/dist/configs/CanvasConfig.d.ts +3237 -0
  6. package/dist/configs/CanvasConfig.js +332 -0
  7. package/dist/configs/build-options.d.ts +10 -0
  8. package/dist/configs/build-options.js +68 -0
  9. package/dist/configs/platform.d.ts +15 -0
  10. package/dist/configs/platform.js +17 -0
  11. package/dist/configs/react-native-system.d.ts +3026 -0
  12. package/dist/configs/react-native-system.js +64 -0
  13. package/dist/configs/system.d.ts +2771 -0
  14. package/dist/configs/system.js +74 -0
  15. package/dist/css/properties.generated.d.ts +14 -0
  16. package/dist/css/properties.generated.js +6260 -0
  17. package/dist/css/value-type.d.ts +48 -0
  18. package/dist/css/value-type.js +131 -0
  19. package/dist/css/values.d.ts +33 -0
  20. package/dist/css/values.js +116 -0
  21. package/dist/entities/native/NativeModifier.d.ts +25 -0
  22. package/dist/entities/native/NativeModifier.js +41 -0
  23. package/dist/entities/native/NativeSettings.d.ts +44 -0
  24. package/dist/entities/native/NativeSettings.js +39 -0
  25. package/dist/entities/native/NativeStyleProperty.d.ts +355 -0
  26. package/dist/entities/native/NativeStyleProperty.js +28 -0
  27. package/dist/entities/native/NativeToken.d.ts +31 -0
  28. package/dist/entities/native/NativeToken.js +49 -0
  29. package/dist/entities/system/CanvasRole.d.ts +34 -0
  30. package/dist/entities/system/CanvasRole.js +45 -0
  31. package/dist/entities/system/Component.d.ts +1287 -0
  32. package/dist/entities/system/Component.js +1840 -0
  33. package/dist/entities/system/Composite.d.ts +12 -0
  34. package/dist/entities/system/Composite.js +26 -0
  35. package/dist/entities/system/Device.d.ts +11 -0
  36. package/dist/entities/system/Device.js +18 -0
  37. package/dist/entities/system/File.d.ts +72 -0
  38. package/dist/entities/system/File.js +136 -0
  39. package/dist/entities/system/Font.d.ts +48 -0
  40. package/dist/entities/system/Font.js +56 -0
  41. package/dist/entities/system/GlobalStyle.d.ts +26 -0
  42. package/dist/entities/system/GlobalStyle.js +54 -0
  43. package/dist/entities/system/Guidance.d.ts +85 -0
  44. package/dist/entities/system/Guidance.js +59 -0
  45. package/dist/entities/system/GuidanceStyle.d.ts +14 -0
  46. package/dist/entities/system/GuidanceStyle.js +8 -0
  47. package/dist/entities/system/Icon.d.ts +46 -0
  48. package/dist/entities/system/Icon.js +46 -0
  49. package/dist/entities/system/LinkedSystem.d.ts +504 -0
  50. package/dist/entities/system/LinkedSystem.js +814 -0
  51. package/dist/entities/system/Modifier.d.ts +92 -0
  52. package/dist/entities/system/Modifier.js +120 -0
  53. package/dist/entities/system/Motion.d.ts +28 -0
  54. package/dist/entities/system/Motion.js +48 -0
  55. package/dist/entities/system/Operation.d.ts +100 -0
  56. package/dist/entities/system/Operation.js +236 -0
  57. package/dist/entities/system/Package.d.ts +42 -0
  58. package/dist/entities/system/Package.js +75 -0
  59. package/dist/entities/system/Settings.d.ts +94 -0
  60. package/dist/entities/system/Settings.js +166 -0
  61. package/dist/entities/system/StyleProperty.d.ts +135 -0
  62. package/dist/entities/system/StyleProperty.js +438 -0
  63. package/dist/entities/system/Token.d.ts +67 -0
  64. package/dist/entities/system/Token.js +129 -0
  65. package/dist/entities/system/Tool.d.ts +134 -0
  66. package/dist/entities/system/Tool.js +124 -0
  67. package/dist/entities/system/color.d.ts +64 -0
  68. package/dist/entities/system/color.js +123 -0
  69. package/dist/entities/system/component-module.d.ts +63 -0
  70. package/dist/entities/system/component-module.js +258 -0
  71. package/dist/entities/system/copy-plan.d.ts +98 -0
  72. package/dist/entities/system/copy-plan.js +451 -0
  73. package/dist/entities/system/defineComponent.d.ts +428 -0
  74. package/dist/entities/system/defineComponent.js +337 -0
  75. package/dist/entities/system/element.d.ts +101 -0
  76. package/dist/entities/system/element.js +171 -0
  77. package/dist/entities/system/icon-library.d.ts +64 -0
  78. package/dist/entities/system/icon-library.js +112 -0
  79. package/dist/entities/system/icon-metadata.d.ts +72 -0
  80. package/dist/entities/system/icon-metadata.js +111 -0
  81. package/dist/entities/system/link-declaration.d.ts +27 -0
  82. package/dist/entities/system/link-declaration.js +64 -0
  83. package/dist/entities/system/link-plan.d.ts +160 -0
  84. package/dist/entities/system/link-plan.js +770 -0
  85. package/dist/entities/system/runtime-modules.d.ts +25 -0
  86. package/dist/entities/system/runtime-modules.js +38 -0
  87. package/dist/entities/system/style-bag.d.ts +20 -0
  88. package/dist/entities/system/style-bag.js +246 -0
  89. package/dist/entities/system/token-index.d.ts +89 -0
  90. package/dist/entities/system/token-index.js +112 -0
  91. package/dist/framework/Config.d.ts +2472 -0
  92. package/dist/framework/Config.js +5023 -0
  93. package/dist/framework/Entity.d.ts +127 -0
  94. package/dist/framework/Entity.js +125 -0
  95. package/dist/framework/authoring.d.ts +24 -0
  96. package/dist/framework/authoring.js +7 -0
  97. package/dist/framework/change-hooks.d.ts +119 -0
  98. package/dist/framework/change-hooks.js +131 -0
  99. package/dist/framework/changes.d.ts +88 -0
  100. package/dist/framework/changes.js +246 -0
  101. package/dist/framework/class-names.d.ts +260 -0
  102. package/dist/framework/class-names.js +630 -0
  103. package/dist/framework/coalesce.d.ts +25 -0
  104. package/dist/framework/coalesce.js +60 -0
  105. package/dist/framework/config-op.d.ts +76 -0
  106. package/dist/framework/config-op.js +43 -0
  107. package/dist/framework/config-operation-kind.d.ts +14 -0
  108. package/dist/framework/config-operation-kind.js +14 -0
  109. package/dist/framework/config-ops.d.ts +34 -0
  110. package/dist/framework/config-ops.js +187 -0
  111. package/dist/framework/defineConfig.d.ts +196 -0
  112. package/dist/framework/defineConfig.js +100 -0
  113. package/dist/framework/defineDerivedEntity.d.ts +74 -0
  114. package/dist/framework/defineDerivedEntity.js +83 -0
  115. package/dist/framework/defineEntity.d.ts +318 -0
  116. package/dist/framework/defineEntity.js +183 -0
  117. package/dist/framework/defineSubEntity.d.ts +148 -0
  118. package/dist/framework/defineSubEntity.js +121 -0
  119. package/dist/framework/derived-mutations.d.ts +20 -0
  120. package/dist/framework/derived-mutations.js +38 -0
  121. package/dist/framework/entity-search.d.ts +29 -0
  122. package/dist/framework/entity-search.js +117 -0
  123. package/dist/framework/inline-sources.d.ts +49 -0
  124. package/dist/framework/inline-sources.js +388 -0
  125. package/dist/framework/layer-styles.d.ts +25 -0
  126. package/dist/framework/layer-styles.js +49 -0
  127. package/dist/framework/memo.d.ts +48 -0
  128. package/dist/framework/memo.js +84 -0
  129. package/dist/framework/overlay.d.ts +49 -0
  130. package/dist/framework/overlay.js +17 -0
  131. package/dist/framework/plan.d.ts +49 -0
  132. package/dist/framework/plan.js +73 -0
  133. package/dist/framework/projections.d.ts +480 -0
  134. package/dist/framework/projections.js +974 -0
  135. package/dist/framework/prop-surface.d.ts +132 -0
  136. package/dist/framework/prop-surface.js +278 -0
  137. package/dist/framework/ref-graph.d.ts +71 -0
  138. package/dist/framework/ref-graph.js +158 -0
  139. package/dist/framework/ref-integrity.d.ts +55 -0
  140. package/dist/framework/ref-integrity.js +171 -0
  141. package/dist/framework/registered.d.ts +95 -0
  142. package/dist/framework/registry-dir.d.ts +42 -0
  143. package/dist/framework/registry-dir.js +48 -0
  144. package/dist/framework/registry.d.ts +300 -0
  145. package/dist/framework/registry.js +104 -0
  146. package/dist/framework/rejection.d.ts +58 -0
  147. package/dist/framework/rejection.js +111 -0
  148. package/dist/framework/rename-inference.d.ts +26 -0
  149. package/dist/framework/rename-inference.js +50 -0
  150. package/dist/framework/render-spec.d.ts +296 -0
  151. package/dist/framework/render-spec.js +809 -0
  152. package/dist/framework/schema-version.d.ts +140 -0
  153. package/dist/framework/schema-version.js +214 -0
  154. package/dist/framework/schemas.d.ts +109 -0
  155. package/dist/framework/schemas.js +615 -0
  156. package/dist/framework/session.d.ts +196 -0
  157. package/dist/framework/session.js +367 -0
  158. package/dist/framework/signature.d.ts +15 -0
  159. package/dist/framework/signature.js +83 -0
  160. package/dist/framework/snapshot.d.ts +115 -0
  161. package/dist/framework/snapshot.js +277 -0
  162. package/dist/framework/source-integrity.d.ts +226 -0
  163. package/dist/framework/source-integrity.js +478 -0
  164. package/dist/framework/sources.d.ts +211 -0
  165. package/dist/framework/sources.js +89 -0
  166. package/dist/framework/utils/compiled-schema.d.ts +23 -0
  167. package/dist/framework/utils/compiled-schema.js +46 -0
  168. package/dist/framework/utils/content-key.d.ts +15 -0
  169. package/dist/framework/utils/content-key.js +33 -0
  170. package/dist/framework/utils/enumerated.d.ts +13 -0
  171. package/dist/framework/utils/enumerated.js +19 -0
  172. package/dist/framework/utils/field-path.d.ts +95 -0
  173. package/dist/framework/utils/field-path.js +136 -0
  174. package/dist/framework/utils/field-schema.d.ts +55 -0
  175. package/dist/framework/utils/field-schema.js +183 -0
  176. package/dist/framework/utils/group.d.ts +37 -0
  177. package/dist/framework/utils/group.js +13 -0
  178. package/dist/framework/utils/package-path.d.ts +37 -0
  179. package/dist/framework/utils/package-path.js +61 -0
  180. package/dist/framework/utils/refs.d.ts +194 -0
  181. package/dist/framework/utils/refs.js +403 -0
  182. package/dist/framework/validate-spec.d.ts +27 -0
  183. package/dist/framework/validate-spec.js +45 -0
  184. package/dist/framework/value-domain.d.ts +26 -0
  185. package/dist/framework/value-domain.js +202 -0
  186. package/dist/framework/views-facade.d.ts +15 -0
  187. package/dist/framework/views-facade.js +19 -0
  188. package/dist/index.d.ts +90 -42
  189. package/dist/index.js +86 -37
  190. package/dist/migrations/2.0.0/raw-css.d.ts +11 -0
  191. package/dist/migrations/2.0.0/raw-css.js +72 -0
  192. package/dist/migrations/2.0.0/v1-artifact.d.ts +1559 -0
  193. package/dist/migrations/2.0.0/v1-artifact.js +1018 -0
  194. package/dist/migrations/20260908171448_settings_as_kind.d.ts +22 -0
  195. package/dist/migrations/20260908171448_settings_as_kind.js +89 -0
  196. package/dist/migrations/20260908194245_visible_state_pointer.d.ts +19 -0
  197. package/dist/migrations/20260908194245_visible_state_pointer.js +115 -0
  198. package/dist/migrations/20260909183001_icon_knockout_variants.d.ts +18 -0
  199. package/dist/migrations/20260909183001_icon_knockout_variants.js +8 -0
  200. package/dist/migrations/20260910212453_linked_system_link_ops.d.ts +13 -0
  201. package/dist/migrations/20260910212453_linked_system_link_ops.js +8 -0
  202. package/dist/migrations/index.d.ts +2 -0
  203. package/dist/migrations/index.js +2 -0
  204. package/dist/react-native/style-keys.generated.d.ts +10 -0
  205. package/dist/react-native/style-keys.generated.js +167 -0
  206. package/dist/renderer/RendererErrorBoundary.d.ts +32 -5
  207. package/dist/renderer/RendererErrorBoundary.js +59 -10
  208. package/dist/renderer/UdsRenderer.d.ts +11 -10
  209. package/dist/renderer/UdsRenderer.js +1 -1
  210. package/dist/renderer/assetEntries.d.ts +37 -0
  211. package/dist/renderer/assetEntries.js +39 -0
  212. package/dist/renderer/assetRenderable.d.ts +14 -6
  213. package/dist/renderer/assetRenderable.js +8 -2
  214. package/dist/renderer/componentEntry.d.ts +58 -0
  215. package/dist/renderer/componentEntry.js +71 -0
  216. package/dist/renderer/icon-library.d.ts +20 -0
  217. package/dist/renderer/index.d.ts +7 -7
  218. package/dist/renderer/index.js +5 -5
  219. package/dist/renderer/primitives/SlotRenderer.d.ts +1 -1
  220. package/dist/renderer/primitives/SlotRenderer.js +1 -1
  221. package/dist/renderer/runtimeComponent.d.ts +33 -0
  222. package/dist/renderer/runtimeComponent.js +113 -0
  223. package/dist/renderer/spec-content.d.ts +43 -0
  224. package/dist/renderer/spec-content.js +95 -0
  225. package/dist/renderer/wrapRegistry.d.ts +22 -37
  226. package/dist/renderer/wrapRegistry.js +10 -20
  227. package/dist/renderer/wrappers/event-bridge.js +6 -5
  228. package/dist/renderer/wrappers/hex-normalize.js +6 -5
  229. package/dist/renderer/wrappers/html-aliases.d.ts +7 -2
  230. package/dist/renderer/wrappers/html-aliases.js +36 -19
  231. package/dist/renderer/wrappers/inline-styles.js +7 -6
  232. package/dist/spec/asset-jsx.d.ts +18 -5
  233. package/dist/spec/asset-jsx.js +27 -16
  234. package/dist/spec/collapse-text-labels.d.ts +5 -15
  235. package/dist/spec/collapse-text-labels.js +26 -19
  236. package/dist/spec/empty-node-slots.d.ts +56 -34
  237. package/dist/spec/empty-node-slots.js +87 -47
  238. package/dist/spec/index.d.ts +21 -10
  239. package/dist/spec/index.js +21 -10
  240. package/dist/spec/jsxToSpec.d.ts +14 -9
  241. package/dist/spec/jsxToSpec.js +20 -3
  242. package/dist/spec/preview-elements.d.ts +63 -0
  243. package/dist/spec/preview-elements.js +89 -0
  244. package/dist/spec/rewrite-refs.d.ts +58 -0
  245. package/dist/spec/rewrite-refs.js +250 -0
  246. package/dist/spec/specToJsx.js +18 -29
  247. package/dist/tsconfig.tsbuildinfo +1 -1
  248. package/package.json +39 -52
  249. package/dist/AssetGroup.d.ts +0 -77
  250. package/dist/AssetGroup.js +0 -125
  251. package/dist/Component.d.ts +0 -333
  252. package/dist/Component.js +0 -1061
  253. package/dist/ComponentGroup.d.ts +0 -22
  254. package/dist/ComponentGroup.js +0 -51
  255. package/dist/CompositeStyle.d.ts +0 -30
  256. package/dist/CompositeStyle.js +0 -59
  257. package/dist/Config.d.ts +0 -528
  258. package/dist/Config.js +0 -1712
  259. package/dist/Mode.d.ts +0 -41
  260. package/dist/Mode.js +0 -81
  261. package/dist/Modifier.d.ts +0 -51
  262. package/dist/Modifier.js +0 -97
  263. package/dist/MotionDef.d.ts +0 -81
  264. package/dist/MotionDef.js +0 -212
  265. package/dist/Props.d.ts +0 -332
  266. package/dist/Props.js +0 -35
  267. package/dist/Provider.d.ts +0 -20
  268. package/dist/Provider.js +0 -14
  269. package/dist/StyleProp.d.ts +0 -145
  270. package/dist/StyleProp.js +0 -239
  271. package/dist/Token.d.ts +0 -76
  272. package/dist/Token.js +0 -133
  273. package/dist/TokenGroup.d.ts +0 -33
  274. package/dist/TokenGroup.js +0 -69
  275. package/dist/asset-kind.d.ts +0 -55
  276. package/dist/asset-kind.js +0 -29
  277. package/dist/asset-value.d.ts +0 -23
  278. package/dist/asset-value.js +0 -40
  279. package/dist/brands.d.ts +0 -30
  280. package/dist/brands.js +0 -20
  281. package/dist/captureCallerPath.d.ts +0 -48
  282. package/dist/captureCallerPath.js +0 -95
  283. package/dist/colorExpressions.d.ts +0 -131
  284. package/dist/colorExpressions.js +0 -148
  285. package/dist/component-referrers.d.ts +0 -30
  286. package/dist/component-referrers.js +0 -40
  287. package/dist/config-diagnostics.d.ts +0 -21
  288. package/dist/config-diagnostics.js +0 -12
  289. package/dist/defineAssetGroup.d.ts +0 -200
  290. package/dist/defineAssetGroup.js +0 -323
  291. package/dist/defineProvider.d.ts +0 -29
  292. package/dist/defineProvider.js +0 -60
  293. package/dist/element-marker.d.ts +0 -63
  294. package/dist/element-marker.js +0 -113
  295. package/dist/entity-utils.d.ts +0 -56
  296. package/dist/entity-utils.js +0 -105
  297. package/dist/extension.d.ts +0 -55
  298. package/dist/extension.js +0 -214
  299. package/dist/factories.d.ts +0 -863
  300. package/dist/factories.js +0 -475
  301. package/dist/font-face.d.ts +0 -25
  302. package/dist/font-face.js +0 -72
  303. package/dist/foreign-component-name.d.ts +0 -21
  304. package/dist/foreign-component-name.js +0 -42
  305. package/dist/interpolate.d.ts +0 -20
  306. package/dist/interpolate.js +0 -10
  307. package/dist/jsx/__fixtures__/cross-component-preview.d.ts +0 -3
  308. package/dist/jsx/__fixtures__/cross-component-preview.js +0 -15
  309. package/dist/jsx/jsx-dev-runtime.d.ts +0 -15
  310. package/dist/jsx/jsx-dev-runtime.js +0 -11
  311. package/dist/jsx/jsx-runtime.d.ts +0 -48
  312. package/dist/jsx/jsx-runtime.js +0 -305
  313. package/dist/linked-system-pins.d.ts +0 -30
  314. package/dist/linked-system-pins.js +0 -45
  315. package/dist/linkedNodePrefixes.d.ts +0 -73
  316. package/dist/linkedNodePrefixes.js +0 -99
  317. package/dist/markers.d.ts +0 -235
  318. package/dist/markers.js +0 -70
  319. package/dist/motion-constants.d.ts +0 -37
  320. package/dist/motion-constants.js +0 -61
  321. package/dist/native/NativeConfig.d.ts +0 -56
  322. package/dist/native/NativeConfig.js +0 -162
  323. package/dist/native/assets.d.ts +0 -20
  324. package/dist/native/assets.js +0 -17
  325. package/dist/native/components.d.ts +0 -139
  326. package/dist/native/components.js +0 -67
  327. package/dist/native/index.d.ts +0 -18
  328. package/dist/native/index.js +0 -17
  329. package/dist/native/modes.d.ts +0 -10
  330. package/dist/native/modes.js +0 -11
  331. package/dist/native/types.d.ts +0 -95
  332. package/dist/native/types.js +0 -0
  333. package/dist/native/validation.d.ts +0 -8
  334. package/dist/native/validation.js +0 -885
  335. package/dist/native/values.d.ts +0 -7
  336. package/dist/native/values.js +0 -15
  337. package/dist/native.d.ts +0 -12
  338. package/dist/native.js +0 -10
  339. package/dist/refs.d.ts +0 -204
  340. package/dist/refs.js +0 -129
  341. package/dist/registry-aliases.d.ts +0 -33
  342. package/dist/registry-aliases.js +0 -35
  343. package/dist/registry-dir.d.ts +0 -22
  344. package/dist/registry-dir.js +0 -10
  345. package/dist/renderer/makeRegistry.d.ts +0 -34
  346. package/dist/renderer/makeRegistry.js +0 -52
  347. package/dist/renderer/makeUdsRenderer.d.ts +0 -13
  348. package/dist/renderer/makeUdsRenderer.js +0 -51
  349. package/dist/renderer/wrappers/component-slots.d.ts +0 -41
  350. package/dist/renderer/wrappers/component-slots.js +0 -66
  351. package/dist/renderer/wrappers/slot-resolution.d.ts +0 -25
  352. package/dist/renderer/wrappers/slot-resolution.js +0 -68
  353. package/dist/renderer/wrappers/void-elements.d.ts +0 -37
  354. package/dist/renderer/wrappers/void-elements.js +0 -40
  355. package/dist/spec/layer-props.d.ts +0 -52
  356. package/dist/spec/layer-props.js +0 -149
  357. package/dist/spec/preview-controls.d.ts +0 -44
  358. package/dist/spec/preview-controls.js +0 -139
  359. package/dist/spec/slot-refs.d.ts +0 -39
  360. package/dist/spec/slot-refs.js +0 -56
  361. package/dist/token-override-rows.d.ts +0 -68
  362. package/dist/token-override-rows.js +0 -233
  363. package/dist/tokenValueType.d.ts +0 -34
  364. package/dist/tokenValueType.js +0 -138
  365. package/dist/types/css-properties.d.ts +0 -233
  366. package/dist/types/css-properties.js +0 -14
  367. package/dist/types/css-property-keywords.d.ts +0 -156
  368. package/dist/types/css-property-keywords.js +0 -616
  369. package/dist/types/css-values.d.ts +0 -63
  370. package/dist/types/css-values.js +0 -16
  371. package/dist/types.d.ts +0 -1138
  372. package/dist/types.js +0 -12
  373. package/dist/units.d.ts +0 -14
  374. package/dist/units.js +0 -16
  375. package/dist/utils/index.d.ts +0 -4
  376. package/dist/utils/index.js +0 -4
@@ -0,0 +1,136 @@
1
+ //#region src/framework/utils/field-path.ts
2
+ /**
3
+ * A write's ADDRESS, carried in the delta's KEY.
4
+ *
5
+ * `update` / `sub-update` take a partial whose keys are FIELD PATHS. One rule covers every depth:
6
+ * **the value replaces whatever the key addresses**, and `null` removes it.
7
+ *
8
+ * { layers: {…} } → replaces the whole `layers` field
9
+ * { 'layers.root.bg': 'hover' } → replaces one leaf, touching nothing else
10
+ * { 'layers.root.bg': null } → removes that leaf
11
+ * { 'layers.root': null } → removes the whole bag
12
+ *
13
+ * So depth is something the CALLER states rather than something the verb implies — Firestore's
14
+ * `update()` rule, and the reason there is no second "deep" verb. A deep write and a whole-field
15
+ * write differ only in how many segments the key has.
16
+ *
17
+ * The nested-object delta this replaces could not tell those two apart. Merged recursively,
18
+ * `{ value: { warning: {} } }` is both "add a value called `warning`" and "empty the one that is
19
+ * already there", and the merge had to GUESS — it pruned, so adding a variant value applied cleanly
20
+ * and stored nothing: a silent no-op with no rejection to explain it. Under an address there is
21
+ * nothing to guess, because setting and removing are different calls rather than different-looking
22
+ * data.
23
+ *
24
+ * The one thing an address cannot spell is a member key that itself contains a dot (`spacing.2`,
25
+ * which nothing names today — paths separate with `/`). Such a key is reachable by `sub-upsert`,
26
+ * which addresses it whole.
27
+ */
28
+ /** A JSON object — not an array, not a class instance. */
29
+ function isPlainObject(value) {
30
+ return typeof value === "object" && value !== null && !Array.isArray(value);
31
+ }
32
+ /**
33
+ * The segments a delta key addresses.
34
+ *
35
+ * A key is a PATH when it contains a `.` AND its first segment names a field of the thing being
36
+ * written — decidable off the target's own schema, so it is a rule rather than a guess. A key that
37
+ * fails either test addresses one field, dot and all, which is what keeps a literal dotted key
38
+ * writable at the depth it lives at.
39
+ */
40
+ function pathSegments(key, isField) {
41
+ const dot = key.indexOf(".");
42
+ if (dot === -1) return [key];
43
+ return isField(key.slice(0, dot)) ? key.split(".") : [key];
44
+ }
45
+ /**
46
+ * A partial over one section of an item, as the item-level delta that writes it: every key prefixed by
47
+ * the section's field, so `{ prefix: 'acme' }` on `css` becomes `{ 'css.prefix': 'acme' }`. A value that
48
+ * is not a record writes the section whole.
49
+ */
50
+ function sectionDelta(field, data) {
51
+ if (!isPlainObject(data)) return { [field]: data };
52
+ return Object.fromEntries(Object.entries(data).map(([key, value]) => [`${field}.${key}`, value]));
53
+ }
54
+ /**
55
+ * `body` with `value` at `segments` — assigned, or REMOVED when `value` is `null`. Neither input is
56
+ * mutated.
57
+ *
58
+ * Two rules about containers along the way, and both follow from "the value replaces what the key
59
+ * addresses":
60
+ *
61
+ * - An intermediate that is missing, or is a scalar, becomes a container. The caller addressed
62
+ * something inside it, which is a caller saying one belongs there.
63
+ * - A removal that EMPTIES a container takes the container with it, except at the first segment —
64
+ * those are the target's own declared fields, and a rule whose `layers` bag has been cleared is
65
+ * still a rule with an empty bag, not a rule missing a required field. Removing the field itself
66
+ * is what `null` AT that segment says. A SET never prunes: an empty object a caller wrote is a
67
+ * value.
68
+ */
69
+ function setAtPath(body, segments, value, depth = 0) {
70
+ const [head, ...rest] = segments;
71
+ if (head === void 0) return body;
72
+ const next = { ...body };
73
+ if (rest.length === 0) {
74
+ if (value === null) delete next[head];
75
+ else next[head] = value;
76
+ return next;
77
+ }
78
+ const written = setAtPath(isPlainObject(next[head]) ? next[head] : {}, rest, value, depth + 1);
79
+ if (depth > 0 && value === null && Object.keys(written).length === 0) delete next[head];
80
+ else next[head] = written;
81
+ return next;
82
+ }
83
+ /**
84
+ * A path-keyed delta applied to a body, entry by entry in the order the caller wrote them.
85
+ *
86
+ * Order matters and is the caller's: two entries may address the same subtree, and the second is
87
+ * meant to win. That is also what makes one batch safe where a read-merge-write pair was not.
88
+ */
89
+ function applyPathDelta(current, delta, isField) {
90
+ let out = current;
91
+ for (const [key, value] of Object.entries(delta)) out = setAtPath(out, pathSegments(key, isField), value);
92
+ return out;
93
+ }
94
+ /**
95
+ * The inverse of {@link applyPathDelta}: the path-keyed delta that turns `existing` into `desired`,
96
+ * over `fields` — one entry per changed member (`null` removes), nothing restated. This is what
97
+ * makes a reconciling writer produce patches that SAY what the gesture did: a prop edit reads back
98
+ * as `props.bg`, not as a whole-body replace.
99
+ *
100
+ * Descent stops exactly where addressing stops, so applying the delta always reproduces `desired`:
101
+ * both sides must be plain records (an array, a ref, a scalar replaces at its own address), every
102
+ * member key must be dot-free (a dotted key can't be addressed — the record writes whole), and a
103
+ * NESTED record emptied of members writes whole, since {@link setAtPath} prunes a container a
104
+ * removal empties. A declared field is never pruned there, so at the field level the same
105
+ * emptying stays addressed.
106
+ *
107
+ * `same` is the caller's structural equality — bodies hold refs, and whether two spellings of one
108
+ * are equal is the caller's to say.
109
+ */
110
+ function pathDelta({ existing, desired, fields, same }) {
111
+ const delta = {};
112
+ const isRef = (value) => typeof value?.__ref === "string";
113
+ const walk = (address, before, after, depth) => {
114
+ if (same(before, after)) return;
115
+ const keys = isPlainObject(before) && isPlainObject(after) ? [...new Set([...Object.keys(before), ...Object.keys(after)])] : void 0;
116
+ if (!(keys !== void 0 && keys.length > 0 && (depth === 0 || Object.keys(after).length > 0) && !isRef(before) && !isRef(after) && keys.every((key) => !key.includes(".")))) {
117
+ delta[address] = after === void 0 ? null : after;
118
+ return;
119
+ }
120
+ for (const key of keys) walk(`${address}.${key}`, before[key], after[key], depth + 1);
121
+ };
122
+ for (const field of fields) walk(field, existing[field], desired[field], 0);
123
+ return delta;
124
+ }
125
+ /** A field predicate over a known list of names — an entity's `fieldKeys`, straight off the kind. */
126
+ function namedFields(names) {
127
+ const declared = new Set(names);
128
+ return (name) => declared.has(name);
129
+ }
130
+ /** The FIELDS a delta touched — every key's first segment. What a write reports as changed, so work
131
+ * scoped to written fields (member coercion) covers the same set the delta reached. */
132
+ function touchedFields(delta, isField) {
133
+ return new Set(Object.keys(delta).map((key) => pathSegments(key, isField)[0]));
134
+ }
135
+ //#endregion
136
+ export { applyPathDelta, isPlainObject, namedFields, pathDelta, pathSegments, sectionDelta, setAtPath, touchedFields };
@@ -0,0 +1,55 @@
1
+ import { z } from "zod";
2
+
3
+ //#region src/framework/utils/field-schema.d.ts
4
+ /** A kind's fields: a flat object, or a union discriminated on one field for kinds whose
5
+ * shape varies (each member a `z.object`). */
6
+ type FieldsSchema = z.ZodObject<z.ZodRawShape> | z.ZodDiscriminatedUnion<readonly z.ZodObject<z.ZodRawShape>[]>;
7
+ /** Distribute over a union first, then drop each member's index signature so an empty
8
+ * `z.object({})` (which infers to `Record<string, never>`) intersects cleanly with the
9
+ * metadata below. Real declared keys are kept; only the catch-all index is removed. */
10
+ type RemoveIndex<T> = T extends unknown ? { [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K] } : never;
11
+ /** The typed author/create body for a schema — the schema's input shape (so a field with
12
+ * a zod `.default()` is optional to author; it's coerced in) plus the universal metadata
13
+ * every entity may carry. Over a discriminated union this stays a union, so authoring one
14
+ * member's fields never bleeds into another's. */
15
+ type CreateInput<S extends FieldsSchema> = RemoveIndex<z.input<S>> & {
16
+ label?: string;
17
+ description?: string;
18
+ copiedFrom?: string;
19
+ hidden?: boolean;
20
+ deprecated?: boolean;
21
+ guidance?: string;
22
+ };
23
+ /** The create validator — the field schema plus metadata (the storage shape; a value
24
+ * storage accepts is creatable — no artificial narrowing at the entity layer). A union
25
+ * extends each member so the discriminant still selects one strict shape. `safeExtend`, so a
26
+ * check a kind declares across its fields (a preview prop naming a prop the body doesn't
27
+ * declare) survives: `extend` drops an object's checks. */
28
+ declare function deriveCreateSchema(schema: FieldsSchema): z.ZodTypeAny;
29
+ /**
30
+ * The update validator — a partial whose keys are field paths ({@link applyPathDelta}).
31
+ *
32
+ * Loose, and that is load-bearing rather than lax: `layers.root.bg` is not a declared field, so a
33
+ * schema that stripped unknown keys (zod's default) would drop every deep write on the floor and
34
+ * report success. What the key names is checked when the delta is applied — the path's head must be a
35
+ * field — and the result of applying it is then validated against the create schema, which is where
36
+ * value types, cross-field checks and coercions all live. So this schema's job is to describe the
37
+ * fields a caller may name and to type the whole-field case; it is deliberately not the gate.
38
+ */
39
+ declare function deriveUpdateSchema(schema: FieldsSchema): z.ZodTypeAny;
40
+ /**
41
+ * Whether a name is a field of the thing being written — what {@link pathSegments} asks to decide
42
+ * whether a dotted delta key is an address or one literal key.
43
+ *
44
+ * Liberal by construction: a union contributes every member's keys, and a record contributes all
45
+ * names, because a record's keys are its fields (a component's `layers` bag is addressed by layer
46
+ * name). Metadata counts too, so `label` is namable wherever it is storable. A name this says no to
47
+ * is written as one key, dot and all, which is the safe answer — the create schema then judges it.
48
+ */
49
+ declare function declaredField(schema: z.ZodTypeAny | undefined): (name: string) => boolean;
50
+ /** The declared field names, in order — hydration and `toJSON` walk these. A union yields
51
+ * the union of every member's keys (discriminant first), so hydration copies whichever
52
+ * fields the stored member actually carries. */
53
+ declare function fieldKeys(schema: FieldsSchema): string[];
54
+ //#endregion
55
+ export { CreateInput, FieldsSchema, declaredField, deriveCreateSchema, deriveUpdateSchema, fieldKeys };
@@ -0,0 +1,183 @@
1
+ import { z } from "zod";
2
+ //#region src/framework/utils/field-schema.ts
3
+ /**
4
+ * An entity declares its fields as a plain `z.object({ ... })` — optionality, value types,
5
+ * and validation come straight from zod (`z.string().optional()`), no custom dsl. Everything
6
+ * downstream (typed bodies, create/update validators, hydration) derives from that one
7
+ * schema.
8
+ *
9
+ * A kind whose shape genuinely varies by a discriminant (Motion: `runtime: 'css'` needs
10
+ * `keyframes`, `runtime: 'js'` carries interaction state instead) may instead declare a
11
+ * `z.discriminatedUnion` — so the coupling is a type, not a runtime hope. The three
12
+ * derivations below handle both: an object extends/partials its shape directly; a union
13
+ * extends/partials each member and re-composes, keeping the discriminant intact.
14
+ */
15
+ /**
16
+ * Universal editable metadata — every entity's create body may carry it, on an item and on a group
17
+ * node alike.
18
+ *
19
+ * `copiedFrom` is where a copied entity was taken from, as `<path>@<slug>`: the source's spelling of
20
+ * the path and the pin it came through. A plain string rather than a ref, because a copy stands on its
21
+ * own — it must not become a dependency on the pin, and dropping the pin must not delete it. Written by
22
+ * `linked-system/copy`; absent on an entity authored here.
23
+ *
24
+ * `hidden` and `deprecated` are the two ways to retire an entity short of deleting it. Both keep it
25
+ * registered, resolving and emitting, and take it out of every surface that offers values to pick
26
+ * from. `deprecated` additionally flags every existing use, so it can be worked through. Set on a
27
+ * group node, either applies to every member; `Config.hidden` and `Config.deprecated` read both.
28
+ *
29
+ * `guidance` is how to use the entity, as prose for a model composing with the system, in the
30
+ * imperative voice of a guidance rule. `description` says what the thing is for a surface that lists
31
+ * it. The guidance document collects these per kind and the prompt prints them there.
32
+ */
33
+ const METADATA = {
34
+ label: z.string().optional(),
35
+ description: z.string().optional(),
36
+ copiedFrom: z.string().optional(),
37
+ hidden: z.boolean().optional(),
38
+ deprecated: z.boolean().optional(),
39
+ guidance: z.string().optional()
40
+ };
41
+ /**
42
+ * The metadata names a body may carry on top of its kind's own fields — read off {@link metadata}
43
+ * rather than re-listed, so the two cannot disagree.
44
+ *
45
+ * What a caller wants it for is deciding whether a delta key names something: `fieldKeys` covers the
46
+ * declared fields and stops, so a gate built on that alone refuses `label` on every kind. `Entity`
47
+ * hydrates these two separately for the same reason.
48
+ */
49
+ const METADATA_KEYS = Object.keys(METADATA);
50
+ /** Re-compose a discriminated union from transformed members. Each member keeps its literal
51
+ * discriminant at runtime, but mapping over the erased `ZodObject<ZodRawShape>` members
52
+ * hides that literal from `discriminatedUnion`'s tuple constraint — so the one bridging cast
53
+ * lives here rather than at every call site. */
54
+ function composeDiscriminated(discriminator, members) {
55
+ return z.discriminatedUnion(discriminator, members);
56
+ }
57
+ /** Make every field of a shape a partial-patch field: an optional field also accepts
58
+ * `null` (the universal "clear this field" affordance — `apply` drops null keys), a
59
+ * required field just becomes optional. Keys in `keep` pass through untouched — used to
60
+ * hold a union's discriminant literal required so the patch still identifies its member. */
61
+ function partializeShape(shape, keep) {
62
+ const out = {};
63
+ for (const [key, field] of Object.entries(shape)) {
64
+ if (keep.has(key)) {
65
+ out[key] = field;
66
+ continue;
67
+ }
68
+ const f = field;
69
+ out[key] = (f instanceof z.ZodOptional ? f.unwrap() : f).nullable().optional();
70
+ }
71
+ return out;
72
+ }
73
+ /** The create validator — the field schema plus metadata (the storage shape; a value
74
+ * storage accepts is creatable — no artificial narrowing at the entity layer). A union
75
+ * extends each member so the discriminant still selects one strict shape. `safeExtend`, so a
76
+ * check a kind declares across its fields (a preview prop naming a prop the body doesn't
77
+ * declare) survives: `extend` drops an object's checks. */
78
+ function deriveCreateSchema(schema) {
79
+ if (schema instanceof z.ZodDiscriminatedUnion) return composeDiscriminated(schema.def.discriminator, schema.def.options.map((member) => member.safeExtend(METADATA)));
80
+ return schema.safeExtend(METADATA);
81
+ }
82
+ /**
83
+ * The delta shape — one entry per field a partial may name, each optional and `null`-accepting.
84
+ *
85
+ * A union flattens into one shape rather than staying discriminated, and that is the point: a delta
86
+ * addresses a field, not a member, so requiring the discriminant would mean restating `type` to
87
+ * change a Motion's duration. A key two members declare differently widens to `unknown` — the delta
88
+ * doesn't say which member it is aimed at, and the narrower of two types would refuse a legitimate
89
+ * write. What the delta is actually checked against is the create schema, applied to the result.
90
+ *
91
+ * `undefined` when there is no shape to partial: a member may be a scalar (a component layer is its
92
+ * element), and there is nothing to name inside it.
93
+ */
94
+ function deltaShape(schema) {
95
+ if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable || schema instanceof z.ZodDefault) return deltaShape(unwrapOnce(schema));
96
+ if (schema instanceof z.ZodPipe) return deltaShape(schema.def.in);
97
+ if (schema instanceof z.ZodObject) return partializeShape(schema.shape, /* @__PURE__ */ new Set());
98
+ if (schema instanceof z.ZodUnion || schema instanceof z.ZodDiscriminatedUnion) {
99
+ const out = {};
100
+ const shared = z.unknown().nullable().optional();
101
+ for (const member of schema.options) {
102
+ const fields = deltaShape(member);
103
+ if (!fields) return void 0;
104
+ for (const [key, field] of Object.entries(fields)) out[key] = key in out ? shared : field;
105
+ }
106
+ return out;
107
+ }
108
+ }
109
+ /** One layer of optional/nullable/default off a schema. */
110
+ function unwrapOnce(schema) {
111
+ if (schema instanceof z.ZodDefault) return schema.def.innerType;
112
+ return schema.unwrap();
113
+ }
114
+ /**
115
+ * The update validator — a partial whose keys are field paths ({@link applyPathDelta}).
116
+ *
117
+ * Loose, and that is load-bearing rather than lax: `layers.root.bg` is not a declared field, so a
118
+ * schema that stripped unknown keys (zod's default) would drop every deep write on the floor and
119
+ * report success. What the key names is checked when the delta is applied — the path's head must be a
120
+ * field — and the result of applying it is then validated against the create schema, which is where
121
+ * value types, cross-field checks and coercions all live. So this schema's job is to describe the
122
+ * fields a caller may name and to type the whole-field case; it is deliberately not the gate.
123
+ */
124
+ function deriveUpdateSchema(schema) {
125
+ const metadata = partializeShape(METADATA, /* @__PURE__ */ new Set());
126
+ return z.looseObject({
127
+ ...deltaShape(schema),
128
+ ...metadata
129
+ });
130
+ }
131
+ /** The update (partial) validator for a sub-entity member — {@link deriveUpdateSchema} without the
132
+ * Entity metadata (a layer/prop member isn't an entity, carries no label/description). A member with
133
+ * no shape to name into — a component layer is its element — keeps its own schema: there is no path
134
+ * to write, so an update replaces it. */
135
+ function deriveMemberUpdateSchema(schema) {
136
+ if (schema instanceof z.ZodNullable) return deriveMemberUpdateSchema(schema.unwrap()).nullable();
137
+ const shape = deltaShape(schema);
138
+ return shape ? z.looseObject(shape) : schema;
139
+ }
140
+ /**
141
+ * Whether a name is a field of the thing being written — what {@link pathSegments} asks to decide
142
+ * whether a dotted delta key is an address or one literal key.
143
+ *
144
+ * Liberal by construction: a union contributes every member's keys, and a record contributes all
145
+ * names, because a record's keys are its fields (a component's `layers` bag is addressed by layer
146
+ * name). Metadata counts too, so `label` is namable wherever it is storable. A name this says no to
147
+ * is written as one key, dot and all, which is the safe answer — the create schema then judges it.
148
+ */
149
+ function declaredField(schema) {
150
+ const names = new Set(Object.keys(METADATA));
151
+ let anyName = false;
152
+ const collect = (from) => {
153
+ if (!from) return;
154
+ if (from instanceof z.ZodOptional || from instanceof z.ZodNullable || from instanceof z.ZodDefault) {
155
+ collect(unwrapOnce(from));
156
+ return;
157
+ }
158
+ if (from instanceof z.ZodRecord) {
159
+ anyName = true;
160
+ return;
161
+ }
162
+ if (from instanceof z.ZodObject) {
163
+ for (const key of Object.keys(from.shape)) names.add(key);
164
+ return;
165
+ }
166
+ if (from instanceof z.ZodUnion || from instanceof z.ZodDiscriminatedUnion) for (const member of from.options) collect(member);
167
+ };
168
+ collect(schema);
169
+ return (name) => anyName || names.has(name);
170
+ }
171
+ /** The declared field names, in order — hydration and `toJSON` walk these. A union yields
172
+ * the union of every member's keys (discriminant first), so hydration copies whichever
173
+ * fields the stored member actually carries. */
174
+ function fieldKeys(schema) {
175
+ if (schema instanceof z.ZodDiscriminatedUnion) {
176
+ const keys = [];
177
+ for (const member of schema.def.options) for (const key of Object.keys(member.shape)) if (!keys.includes(key)) keys.push(key);
178
+ return keys;
179
+ }
180
+ return Object.keys(schema.shape);
181
+ }
182
+ //#endregion
183
+ export { METADATA_KEYS, declaredField, deriveCreateSchema, deriveMemberUpdateSchema, deriveUpdateSchema, fieldKeys };
@@ -0,0 +1,37 @@
1
+ import { Ref } from "./refs.js";
2
+ import { CreateInput, FieldsSchema } from "./field-schema.js";
3
+ import { Authored } from "../authoring.js";
4
+
5
+ //#region src/framework/utils/group.d.ts
6
+ declare const GROUP: unique symbol;
7
+ /**
8
+ * One authored entry for a kind: an item body, a group node, a bare shorthand for the primary field,
9
+ * or a NESTED record whose keys extend the path.
10
+ *
11
+ * Recursive because nesting is. A path is a slash-joined name and a config may spell it either way —
12
+ * `'color/text/primary'` or `color: { text: { primary } }` — so a record of these is admissible at
13
+ * every level, exactly as `register` flattens them.
14
+ */
15
+ type AuthoredEntry<F extends FieldsSchema, G extends FieldsSchema> = CreateInput<F> | GroupBody<F, G> | Authored | string | number | Ref | NestedEntries<F, G>;
16
+ /**
17
+ * A record of entries under a shared prefix.
18
+ *
19
+ * Its values are entries in their own right, but never a BARE SHORTHAND. That mirrors the flattener,
20
+ * which treats a record as a prefix only when every value is an object — so a string sitting in one
21
+ * is a malformed item either way, and this is what makes the type say so rather than silently
22
+ * reading `{ valuee: '#fff' }` as a nested token named `valuee`.
23
+ */
24
+ type NestedEntries<F extends FieldsSchema, G extends FieldsSchema> = {
25
+ readonly [key: string]: CreateInput<F> | GroupBody<F, G> | Authored | Ref | NestedEntries<F, G>;
26
+ };
27
+ /** A group node — its own fields, plus the members that live under its path. */
28
+ type GroupBody<F extends FieldsSchema, G extends FieldsSchema> = CreateInput<G> & {
29
+ /** The group's members, keyed by the segment that extends its path. Stating the prefix once is
30
+ * the point: `color: Token.group({ items: { brand } })` rather than `'color/brand'` per entry. */
31
+ readonly items?: Readonly<Record<string, AuthoredEntry<F, G>>>;
32
+ readonly [GROUP]?: true;
33
+ };
34
+ declare function brandGroup<F extends FieldsSchema, G extends FieldsSchema>(meta: GroupBody<F, G>): GroupBody<F, G>;
35
+ declare function isGroupBody(value: unknown): boolean;
36
+ //#endregion
37
+ export { AuthoredEntry, GROUP, GroupBody, brandGroup, isGroupBody };
@@ -0,0 +1,13 @@
1
+ //#region src/framework/utils/group.ts
2
+ const GROUP = Symbol("entity-kit/group");
3
+ function brandGroup(meta) {
4
+ return {
5
+ ...meta,
6
+ [GROUP]: true
7
+ };
8
+ }
9
+ function isGroupBody(value) {
10
+ return typeof value === "object" && value !== null && value[GROUP] === true;
11
+ }
12
+ //#endregion
13
+ export { GROUP, brandGroup, isGroupBody };
@@ -0,0 +1,37 @@
1
+ //#region src/framework/utils/package-path.d.ts
2
+ /**
3
+ * A package specifier → the path its `Package` entities live at.
4
+ *
5
+ * **There is no slug. The path IS the module** — `package:@ariakit/react#TooltipAnchor` — the same
6
+ * choice `File` makes for its src, and for the same reason: a name derived from another name is a
7
+ * second copy that can drift, and a derived name has to stay stable against a set that grows.
8
+ *
9
+ * It used to be a slug (`package:ariakit/TooltipAnchor`), computed over the whole import SET so that
10
+ * two specifiers sharing a scope could both qualify away from it. That made a key depend on what else
11
+ * happened to be imported: `@phosphor-icons/core` arriving beside `@phosphor-icons/react` renamed the
12
+ * latter's group and stranded every stored ref that named it. Declaring the groups froze the answer,
13
+ * at the cost of making every consumer restate imports it had already written. A module is a name npm
14
+ * has already made unique, so using it needs neither a set nor a declaration.
15
+ *
16
+ * Lives in the config package because BOTH sides derive from it: the layers schema serializes a
17
+ * native marker to `package:<module>/<name>` at parse, and codegen's collectors key registry entries
18
+ * and `Package` groups the same way at build. One rule — and now one that cannot be computed two
19
+ * ways, because it consults nothing but the specifier in hand.
20
+ */
21
+ declare const EXPORT_MEMBER = "exports";
22
+ declare function packageName(specifier: string): string;
23
+ /**
24
+ * The stored ref for one export — `package:react-native#Pressable`.
25
+ *
26
+ * The MODULE is the entity and the export is a MEMBER of it, separated by the grammar's own member
27
+ * marker rather than by a `/` and a convention about which segment is which. A `/` cannot do it: an
28
+ * npm specifier contains them (`@ariakit/react`, `motion/react`), so "the last segment is the export"
29
+ * is a guess that `motion/react` and `@phosphor-icons/core` both break — the first is a module that
30
+ * parses as an export called `react`, the second a module that parsed as an export called `core`.
31
+ *
32
+ * The module goes in VERBATIM. `motion/react` and `motion` are different modules even though they are
33
+ * one npm package, and only the exact one regenerates the import the author wrote.
34
+ */
35
+ declare function packageKey(specifier: string, name: string): string;
36
+ //#endregion
37
+ export { EXPORT_MEMBER, packageKey, packageName };
@@ -0,0 +1,61 @@
1
+ //#region src/framework/utils/package-path.ts
2
+ /**
3
+ * A package specifier → the path its `Package` entities live at.
4
+ *
5
+ * **There is no slug. The path IS the module** — `package:@ariakit/react#TooltipAnchor` — the same
6
+ * choice `File` makes for its src, and for the same reason: a name derived from another name is a
7
+ * second copy that can drift, and a derived name has to stay stable against a set that grows.
8
+ *
9
+ * It used to be a slug (`package:ariakit/TooltipAnchor`), computed over the whole import SET so that
10
+ * two specifiers sharing a scope could both qualify away from it. That made a key depend on what else
11
+ * happened to be imported: `@phosphor-icons/core` arriving beside `@phosphor-icons/react` renamed the
12
+ * latter's group and stranded every stored ref that named it. Declaring the groups froze the answer,
13
+ * at the cost of making every consumer restate imports it had already written. A module is a name npm
14
+ * has already made unique, so using it needs neither a set nor a declaration.
15
+ *
16
+ * Lives in the config package because BOTH sides derive from it: the layers schema serializes a
17
+ * native marker to `package:<module>/<name>` at parse, and codegen's collectors key registry entries
18
+ * and `Package` groups the same way at build. One rule — and now one that cannot be computed two
19
+ * ways, because it consults nothing but the specifier in hand.
20
+ */
21
+ /**
22
+ * A specifier stripped to the npm package it installs — `@scope/pkg/sub` → `@scope/pkg`.
23
+ *
24
+ * The unit a GROUP is keyed by, because it is the unit a consumer installs: two specifiers reaching
25
+ * into one package are one dependency. The SUBPATH is not lost — it is the key of the `File.imports`
26
+ * entry that reached it. So the two kinds divide the fact: `File` records what the source WROTE,
27
+ * `Package` records what a consumer INSTALLS.
28
+ *
29
+ * This is also what answers "where does the module end and the export begin" in a stored path — a
30
+ * leading `@` means the first two segments, otherwise the first one, which is npm's own rule. An
31
+ * export name cannot contain a `/`, so there is nothing left ambiguous.
32
+ */
33
+ /** The grammar's member marker, and the FIELD `Package` stores its exports in. Both spelled here so a
34
+ * key and a `memberRef` cannot disagree about the one string that separates a ref's two halves.
35
+ *
36
+ * It is the field name rather than the sub-entity's own name because that is what resolution reads:
37
+ * `ref-integrity`'s `resolves` looks the collection up as `owner[member.slice(0, slash)]`, the same
38
+ * way `component:Input#props/disabled` names the `props` field. */
39
+ const MEMBER = "#";
40
+ const EXPORT_MEMBER = "exports";
41
+ function packageName(specifier) {
42
+ const segments = specifier.split("/");
43
+ return specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0] ?? specifier;
44
+ }
45
+ /**
46
+ * The stored ref for one export — `package:react-native#Pressable`.
47
+ *
48
+ * The MODULE is the entity and the export is a MEMBER of it, separated by the grammar's own member
49
+ * marker rather than by a `/` and a convention about which segment is which. A `/` cannot do it: an
50
+ * npm specifier contains them (`@ariakit/react`, `motion/react`), so "the last segment is the export"
51
+ * is a guess that `motion/react` and `@phosphor-icons/core` both break — the first is a module that
52
+ * parses as an export called `react`, the second a module that parsed as an export called `core`.
53
+ *
54
+ * The module goes in VERBATIM. `motion/react` and `motion` are different modules even though they are
55
+ * one npm package, and only the exact one regenerates the import the author wrote.
56
+ */
57
+ function packageKey(specifier, name) {
58
+ return `package:${specifier}${MEMBER}${name}`;
59
+ }
60
+ //#endregion
61
+ export { EXPORT_MEMBER, packageKey, packageName };