@iris-ui-kit/react 0.1.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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/dist/SidebarLayout-fWQRvK0a.d.cts +26 -0
  3. package/dist/SidebarLayout-fWQRvK0a.d.ts +26 -0
  4. package/dist/admin.cjs +1583 -0
  5. package/dist/admin.cjs.map +1 -0
  6. package/dist/admin.d.cts +183 -0
  7. package/dist/admin.d.ts +183 -0
  8. package/dist/admin.js +9 -0
  9. package/dist/admin.js.map +1 -0
  10. package/dist/async.cjs +97 -0
  11. package/dist/async.cjs.map +1 -0
  12. package/dist/async.d.cts +57 -0
  13. package/dist/async.d.ts +57 -0
  14. package/dist/async.js +5 -0
  15. package/dist/async.js.map +1 -0
  16. package/dist/behaviors.cjs +569 -0
  17. package/dist/behaviors.cjs.map +1 -0
  18. package/dist/behaviors.d.cts +188 -0
  19. package/dist/behaviors.d.ts +188 -0
  20. package/dist/behaviors.js +4 -0
  21. package/dist/behaviors.js.map +1 -0
  22. package/dist/chunk-2TQSTINK.js +541 -0
  23. package/dist/chunk-2TQSTINK.js.map +1 -0
  24. package/dist/chunk-53KFLVIZ.js +68 -0
  25. package/dist/chunk-53KFLVIZ.js.map +1 -0
  26. package/dist/chunk-6BMFMCMQ.js +140 -0
  27. package/dist/chunk-6BMFMCMQ.js.map +1 -0
  28. package/dist/chunk-AUA5GBT6.js +143 -0
  29. package/dist/chunk-AUA5GBT6.js.map +1 -0
  30. package/dist/chunk-DE6V6NOI.js +122 -0
  31. package/dist/chunk-DE6V6NOI.js.map +1 -0
  32. package/dist/chunk-HEJGN6UI.js +78 -0
  33. package/dist/chunk-HEJGN6UI.js.map +1 -0
  34. package/dist/chunk-IDD35UJ6.js +83 -0
  35. package/dist/chunk-IDD35UJ6.js.map +1 -0
  36. package/dist/chunk-J5FB2UB2.js +166 -0
  37. package/dist/chunk-J5FB2UB2.js.map +1 -0
  38. package/dist/chunk-OMOTUHYI.js +66 -0
  39. package/dist/chunk-OMOTUHYI.js.map +1 -0
  40. package/dist/chunk-RZNYIFV2.js +34 -0
  41. package/dist/chunk-RZNYIFV2.js.map +1 -0
  42. package/dist/chunk-SJO74IB3.js +54 -0
  43. package/dist/chunk-SJO74IB3.js.map +1 -0
  44. package/dist/chunk-SORLRLS4.js +53 -0
  45. package/dist/chunk-SORLRLS4.js.map +1 -0
  46. package/dist/chunk-TO7YVSAI.js +64 -0
  47. package/dist/chunk-TO7YVSAI.js.map +1 -0
  48. package/dist/chunk-TQ33XJIK.js +22 -0
  49. package/dist/chunk-TQ33XJIK.js.map +1 -0
  50. package/dist/chunk-UWUUEZCD.js +950 -0
  51. package/dist/chunk-UWUUEZCD.js.map +1 -0
  52. package/dist/chunk-VWCJJRSC.js +1200 -0
  53. package/dist/chunk-VWCJJRSC.js.map +1 -0
  54. package/dist/chunk-WIHBIDVJ.js +54 -0
  55. package/dist/chunk-WIHBIDVJ.js.map +1 -0
  56. package/dist/chunk-XCK4RIXB.js +66 -0
  57. package/dist/chunk-XCK4RIXB.js.map +1 -0
  58. package/dist/chunk-YAHXR2CJ.js +48 -0
  59. package/dist/chunk-YAHXR2CJ.js.map +1 -0
  60. package/dist/chunk-YXIO5THG.js +4 -0
  61. package/dist/chunk-YXIO5THG.js.map +1 -0
  62. package/dist/chunk-ZKBDUWUD.js +156 -0
  63. package/dist/chunk-ZKBDUWUD.js.map +1 -0
  64. package/dist/data.cjs +112 -0
  65. package/dist/data.cjs.map +1 -0
  66. package/dist/data.d.cts +53 -0
  67. package/dist/data.d.ts +53 -0
  68. package/dist/data.js +5 -0
  69. package/dist/data.js.map +1 -0
  70. package/dist/error-boundary.cjs +106 -0
  71. package/dist/error-boundary.cjs.map +1 -0
  72. package/dist/error-boundary.d.cts +41 -0
  73. package/dist/error-boundary.d.ts +41 -0
  74. package/dist/error-boundary.js +6 -0
  75. package/dist/error-boundary.js.map +1 -0
  76. package/dist/floating.cjs +163 -0
  77. package/dist/floating.cjs.map +1 -0
  78. package/dist/floating.d.cts +92 -0
  79. package/dist/floating.d.ts +92 -0
  80. package/dist/floating.js +5 -0
  81. package/dist/floating.js.map +1 -0
  82. package/dist/form.cjs +159 -0
  83. package/dist/form.cjs.map +1 -0
  84. package/dist/form.d.cts +120 -0
  85. package/dist/form.d.ts +120 -0
  86. package/dist/form.js +5 -0
  87. package/dist/form.js.map +1 -0
  88. package/dist/i18n.cjs +100 -0
  89. package/dist/i18n.cjs.map +1 -0
  90. package/dist/i18n.d.cts +50 -0
  91. package/dist/i18n.d.ts +50 -0
  92. package/dist/i18n.js +5 -0
  93. package/dist/i18n.js.map +1 -0
  94. package/dist/index.cjs +16635 -0
  95. package/dist/index.cjs.map +1 -0
  96. package/dist/index.d.cts +2964 -0
  97. package/dist/index.d.ts +2964 -0
  98. package/dist/index.js +12217 -0
  99. package/dist/index.js.map +1 -0
  100. package/dist/layouts.cjs +386 -0
  101. package/dist/layouts.cjs.map +1 -0
  102. package/dist/layouts.d.cts +92 -0
  103. package/dist/layouts.d.ts +92 -0
  104. package/dist/layouts.js +6 -0
  105. package/dist/layouts.js.map +1 -0
  106. package/dist/modal-utils.cjs +168 -0
  107. package/dist/modal-utils.cjs.map +1 -0
  108. package/dist/modal-utils.d.cts +43 -0
  109. package/dist/modal-utils.d.ts +43 -0
  110. package/dist/modal-utils.js +4 -0
  111. package/dist/modal-utils.js.map +1 -0
  112. package/dist/motion.cjs +104 -0
  113. package/dist/motion.cjs.map +1 -0
  114. package/dist/motion.d.cts +41 -0
  115. package/dist/motion.d.ts +41 -0
  116. package/dist/motion.js +4 -0
  117. package/dist/motion.js.map +1 -0
  118. package/dist/provider.cjs +191 -0
  119. package/dist/provider.cjs.map +1 -0
  120. package/dist/provider.d.cts +62 -0
  121. package/dist/provider.d.ts +62 -0
  122. package/dist/provider.js +8 -0
  123. package/dist/provider.js.map +1 -0
  124. package/dist/resource.cjs +61 -0
  125. package/dist/resource.cjs.map +1 -0
  126. package/dist/resource.d.cts +21 -0
  127. package/dist/resource.d.ts +21 -0
  128. package/dist/resource.js +5 -0
  129. package/dist/resource.js.map +1 -0
  130. package/dist/skeletons.cjs +1304 -0
  131. package/dist/skeletons.cjs.map +1 -0
  132. package/dist/skeletons.d.cts +70 -0
  133. package/dist/skeletons.d.ts +70 -0
  134. package/dist/skeletons.js +8 -0
  135. package/dist/skeletons.js.map +1 -0
  136. package/dist/skins.cjs +134 -0
  137. package/dist/skins.cjs.map +1 -0
  138. package/dist/skins.d.cts +45 -0
  139. package/dist/skins.d.ts +45 -0
  140. package/dist/skins.js +5 -0
  141. package/dist/skins.js.map +1 -0
  142. package/dist/theme.cjs +100 -0
  143. package/dist/theme.cjs.map +1 -0
  144. package/dist/theme.d.cts +71 -0
  145. package/dist/theme.d.ts +71 -0
  146. package/dist/theme.js +5 -0
  147. package/dist/theme.js.map +1 -0
  148. package/dist/undo.cjs +73 -0
  149. package/dist/undo.cjs.map +1 -0
  150. package/dist/undo.d.cts +47 -0
  151. package/dist/undo.d.ts +47 -0
  152. package/dist/undo.js +4 -0
  153. package/dist/undo.js.map +1 -0
  154. package/package.json +61 -0
@@ -0,0 +1,191 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ var React3 = require('react');
5
+ var core = require('@iris-ui-kit/core');
6
+ var theme = require('@iris-ui-kit/theme');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+ var skins = require('@iris-ui-kit/skins');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
29
+
30
+ // src/provider/IrisProvider.tsx
31
+ function useStore(store) {
32
+ return React3.useSyncExternalStore(
33
+ store.subscribe,
34
+ store.getState,
35
+ store.getState
36
+ // SSR fallback — same as client snapshot in our case.
37
+ );
38
+ }
39
+ var IrisThemeContext = React3.createContext(null);
40
+ function ThemeProvider({
41
+ store,
42
+ target = null,
43
+ dir = "ltr",
44
+ cspNonce,
45
+ children
46
+ }) {
47
+ const current = useStore(store.store);
48
+ const appliedRef = React3.useRef(null);
49
+ React3.useEffect(() => {
50
+ theme.injectGlobalStyles(cspNonce);
51
+ const el = target ?? document.documentElement;
52
+ appliedRef.current?.revert();
53
+ appliedRef.current = theme.applyTheme(current, el);
54
+ const dirApplied = theme.applyDirection(dir, el);
55
+ return () => {
56
+ appliedRef.current?.revert();
57
+ appliedRef.current = null;
58
+ dirApplied.revert();
59
+ };
60
+ }, [current, target, dir]);
61
+ return /* @__PURE__ */ jsxRuntime.jsx(IrisThemeContext.Provider, { value: { store, current, dir }, children });
62
+ }
63
+ var IrisSkinContext = React3.createContext(null);
64
+ function SkinProvider({ engine, target = null, cspNonce, children }) {
65
+ const current = useStore(engine.store);
66
+ const appliedRef = React3.useRef(null);
67
+ React3.useEffect(() => {
68
+ theme.injectGlobalStyles(cspNonce);
69
+ const el = target ?? document.documentElement;
70
+ appliedRef.current?.revert();
71
+ appliedRef.current = skins.applySkin(current, el);
72
+ return () => {
73
+ appliedRef.current?.revert();
74
+ appliedRef.current = null;
75
+ };
76
+ }, [current, target]);
77
+ return /* @__PURE__ */ jsxRuntime.jsx(IrisSkinContext.Provider, { value: { engine, current }, children });
78
+ }
79
+ var I18nContext = React3__namespace.createContext(null);
80
+ function IrisI18nProvider({
81
+ locale,
82
+ messages,
83
+ i18n,
84
+ autoDirection,
85
+ directionTarget,
86
+ children
87
+ }) {
88
+ const ref = React3__namespace.useRef(null);
89
+ if (ref.current === null) {
90
+ ref.current = i18n ?? core.createI18n({ locale, messages });
91
+ }
92
+ const instance = ref.current;
93
+ React3__namespace.useEffect(() => {
94
+ if (i18n || !locale) return;
95
+ instance.setLocale(locale);
96
+ }, [locale, i18n, instance]);
97
+ React3__namespace.useEffect(() => {
98
+ if (i18n || !messages) return;
99
+ instance.setMessages(messages);
100
+ }, [messages, i18n, instance]);
101
+ React3__namespace.useEffect(() => {
102
+ if (!autoDirection || !locale || typeof document === "undefined") return;
103
+ const el = directionTarget ?? document.documentElement;
104
+ const applied = theme.applyDirection(core.localeDirection(locale), el);
105
+ const prevLang = el.getAttribute("lang");
106
+ el.setAttribute("lang", locale);
107
+ return () => {
108
+ applied.revert();
109
+ if (prevLang === null) el.removeAttribute("lang");
110
+ else el.setAttribute("lang", prevLang);
111
+ };
112
+ }, [autoDirection, locale, directionTarget]);
113
+ return /* @__PURE__ */ jsxRuntime.jsx(I18nContext.Provider, { value: instance, children });
114
+ }
115
+ var PluginStoreContext = React3.createContext(null);
116
+ function IrisProvider({
117
+ theme: theme$1,
118
+ skin,
119
+ dir = "ltr",
120
+ locale,
121
+ messages,
122
+ plugins,
123
+ target = null,
124
+ children
125
+ }) {
126
+ const collected = React3.useMemo(() => core.runPlugins(plugins ?? []), [plugins]);
127
+ const appliedRef = React3.useRef(null);
128
+ React3.useEffect(() => {
129
+ if (typeof document === "undefined") return;
130
+ const el = target ?? document.documentElement;
131
+ appliedRef.current?.revert();
132
+ appliedRef.current = theme.applyCssVars(Object.entries(collected.tokens), el);
133
+ return () => {
134
+ appliedRef.current?.revert();
135
+ appliedRef.current = null;
136
+ };
137
+ }, [collected, target]);
138
+ React3.useEffect(() => () => collected.teardown(), [collected]);
139
+ const value = React3.useMemo(
140
+ () => ({ stores: collected.stores, installed: new Set((plugins ?? []).map((p) => p.name)) }),
141
+ [collected, plugins]
142
+ );
143
+ const merged = { ...collected.messages[locale ?? "en-US"], ...messages ?? {} };
144
+ let tree = /* @__PURE__ */ jsxRuntime.jsx(IrisI18nProvider, { locale, messages: merged, children: /* @__PURE__ */ jsxRuntime.jsx(PluginStoreContext.Provider, { value, children }) });
145
+ if (skin) {
146
+ tree = /* @__PURE__ */ jsxRuntime.jsx(SkinProvider, { engine: skin, target, children: tree });
147
+ }
148
+ if (theme$1) {
149
+ tree = /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { store: theme$1, dir, target, children: tree });
150
+ }
151
+ return tree;
152
+ }
153
+ function usePlugin(name) {
154
+ return React3.useContext(PluginStoreContext)?.installed.has(name) ?? false;
155
+ }
156
+ var warnedKeys = /* @__PURE__ */ new Map();
157
+ function usePluginStore(nsOrKey, key) {
158
+ const ctx = React3.useContext(PluginStoreContext);
159
+ if (!ctx) {
160
+ const displayKey = key !== void 0 ? `${nsOrKey}::${key}` : nsOrKey;
161
+ throw new Error(`[iris-ui] usePluginStore("${displayKey}"): no <IrisProvider> ancestor found`);
162
+ }
163
+ const fullKey = key !== void 0 ? `${nsOrKey}::${key}` : nsOrKey;
164
+ let store = ctx.stores.get(fullKey);
165
+ if (store !== void 0) return store;
166
+ if (key === void 0) {
167
+ store = ctx.stores.get(nsOrKey);
168
+ if (store !== void 0) return store;
169
+ for (const k of ctx.stores.keys()) {
170
+ if (typeof k === "string" && k.endsWith(`::${nsOrKey}`)) {
171
+ if (!warnedKeys.has(nsOrKey)) {
172
+ warnedKeys.set(nsOrKey, true);
173
+ console.warn(
174
+ `[iris-ui] Ambiguous plugin store key "${nsOrKey}". Found "${k}". Use the namespaced form for clarity: usePluginStore("${k}").`
175
+ );
176
+ }
177
+ return ctx.stores.get(k);
178
+ }
179
+ }
180
+ }
181
+ throw new Error(
182
+ `[iris-ui] Plugin store "${fullKey}" not found. Ensure the plugin is installed in IrisProvider and the key is correct.`
183
+ );
184
+ }
185
+
186
+ exports.IrisProvider = IrisProvider;
187
+ exports.PluginStoreContext = PluginStoreContext;
188
+ exports.usePlugin = usePlugin;
189
+ exports.usePluginStore = usePluginStore;
190
+ //# sourceMappingURL=provider.cjs.map
191
+ //# sourceMappingURL=provider.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useStore.ts","../src/theme/ThemeProvider.tsx","../src/skins/SkinProvider.tsx","../src/i18n/context.ts","../src/i18n/I18nProvider.tsx","../src/provider/context.ts","../src/provider/IrisProvider.tsx"],"names":["useSyncExternalStore","createContext","useRef","useEffect","injectGlobalStyles","applyTheme","applyDirection","jsx","applySkin","React2","React3","createI18n","localeDirection","theme","useMemo","runPlugins","applyCssVars","useContext"],"mappings":"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","file":"provider.cjs","sourcesContent":["import * as React from 'react'\nimport { useSyncExternalStore } from 'react'\nimport type { ReadonlyStore, Store } from '@iris-ui-kit/core'\n\n/**\n * Bridge a framework-agnostic `@iris-ui-kit/core` store into React reactivity.\n * Uses React 18's `useSyncExternalStore` — the contract is identical to the\n * one Vue uses via `ref + onMounted` and Solid uses via `createSignal`. The\n * **same** store can power Button, Popover, Dialog, etc. on any framework.\n */\nexport function useStore<T>(store: ReadonlyStore<T>): T {\n return useSyncExternalStore(\n store.subscribe,\n store.getState,\n store.getState, // SSR fallback — same as client snapshot in our case.\n )\n}\n\n/**\n * Subscribe to a DERIVED slice of a core store — the component re-renders only\n * when `selector(state)` changes per `isEqual` (default `Object.is`), not on\n * every store emission. Built on {@link Store.subscribeWith}. Inline closures\n * for `selector`/`isEqual` are fine (captured via refs; the subscription is not\n * re-created between renders).\n */\nexport function useStoreSelector<T, U>(\n store: Store<T>,\n selector: (state: T) => U,\n isEqual?: (a: U, b: U) => boolean,\n): U {\n const [slice, setSlice] = React.useState(() => selector(store.getState()))\n const selRef = React.useRef(selector)\n selRef.current = selector\n const eqRef = React.useRef(isEqual)\n eqRef.current = isEqual\n React.useEffect(() => {\n const read = (s: T): U => selRef.current(s)\n const eq = (a: U, b: U): boolean => (eqRef.current ?? Object.is)(a, b)\n // Re-sync in case the store moved between render and this effect.\n setSlice((prev) => {\n const next = read(store.getState())\n return eq(prev, next) ? prev : next\n })\n return store.subscribeWith(read, setSlice, eq)\n }, [store])\n return slice\n}\n","import { createContext, useContext, useEffect, useRef, type ReactNode } from 'react'\nimport {\n applyDirection,\n applyTheme,\n injectGlobalStyles,\n type ApplyThemeResult,\n type Direction,\n type ThemeStore,\n} from '@iris-ui-kit/theme'\nimport type { IrisTheme } from '@iris-ui-kit/tokens'\nimport { useStore } from '../useStore'\n\ninterface IrisThemeContextValue {\n store: ThemeStore\n current: IrisTheme\n dir: Direction\n}\n\nconst IrisThemeContext = createContext<IrisThemeContextValue | null>(null)\n\nexport interface ThemeProviderProps {\n store: ThemeStore\n target?: HTMLElement | null\n /** Writing direction; sets `dir` on the target for RTL. Default `'ltr'`. */\n dir?: Direction\n /** CSP nonce for the injected global stylesheet. Pass the `nonce` from your\n * server-rendered CSP header when you use `style-src: 'nonce-...'`. */\n cspNonce?: string\n children?: ReactNode\n}\n\n/**\n * Renderless provider that mirrors `<IrisThemeProvider>` from `@iris-ui-kit/vue`:\n * subscribes to the theme store, applies CSS variables to `target` (or\n * `document.documentElement`), reverts on unmount.\n *\n * **Zero business logic** — `applyTheme` / `createThemeStore` come straight\n * from `@iris-ui-kit/theme`. This component is just a 30-line React adapter.\n */\nexport function ThemeProvider({\n store,\n target = null,\n dir = 'ltr',\n cspNonce,\n children,\n}: ThemeProviderProps) {\n const current = useStore(store.store)\n const appliedRef = useRef<ApplyThemeResult | null>(null)\n\n useEffect(() => {\n injectGlobalStyles(cspNonce)\n const el = target ?? document.documentElement\n appliedRef.current?.revert()\n appliedRef.current = applyTheme(current, el)\n const dirApplied = applyDirection(dir, el)\n return () => {\n appliedRef.current?.revert()\n appliedRef.current = null\n dirApplied.revert()\n }\n }, [current, target, dir])\n\n return (\n <IrisThemeContext.Provider value={{ store, current, dir }}>\n {children}\n </IrisThemeContext.Provider>\n )\n}\n\nexport function useThemeContext(): IrisThemeContextValue {\n const ctx = useContext(IrisThemeContext)\n if (!ctx) {\n throw new Error('[iris-ui] useTheme(): no <ThemeProvider> ancestor found')\n }\n return ctx\n}\n\n/**\n * Read the current theme without throwing when there is no `<ThemeProvider>`\n * ancestor. Returns `undefined` outside a provider. Used by theme-aware\n * primitives (e.g. `IrisIcon`) that must still render standalone.\n */\nexport function useThemeOptional(): IrisTheme | undefined {\n return useContext(IrisThemeContext)?.current\n}\n\n/**\n * Current writing direction (`'ltr'` / `'rtl'`) from the nearest\n * `<ThemeProvider>`, or `'ltr'` when there is none. For components that need to\n * branch on direction beyond what CSS logical properties already handle.\n */\nexport function useDirection(): Direction {\n return useContext(IrisThemeContext)?.dir ?? 'ltr'\n}\n","import { createContext, useContext, useEffect, useRef, type ReactNode } from 'react'\nimport { injectGlobalStyles } from '@iris-ui-kit/theme'\nimport {\n applySkin,\n type ApplySkinResult,\n type ResolvedSkin,\n type SkinEngine,\n} from '@iris-ui-kit/skins'\nimport { useStore } from '../useStore'\n\ninterface IrisSkinContextValue {\n engine: SkinEngine\n current: ResolvedSkin\n}\n\nconst IrisSkinContext = createContext<IrisSkinContextValue | null>(null)\n\nexport interface SkinProviderProps {\n engine: SkinEngine\n target?: HTMLElement | null\n /** CSP nonce for the injected global stylesheet. */\n cspNonce?: string\n children?: ReactNode\n}\n\n/**\n * Renderless provider mirroring `<ThemeProvider>`: subscribes to the skin\n * engine's store, applies the resolved skin's CSS vars to `target` (or\n * `document.documentElement`), reverts on unmount. Zero skin logic — all of it\n * lives in `@iris-ui-kit/skins`. Client boundary (tsup prepends `'use client'`).\n */\nexport function SkinProvider({ engine, target = null, cspNonce, children }: SkinProviderProps) {\n const current = useStore(engine.store)\n const appliedRef = useRef<ApplySkinResult | null>(null)\n\n useEffect(() => {\n injectGlobalStyles(cspNonce)\n const el = target ?? document.documentElement\n appliedRef.current?.revert()\n appliedRef.current = applySkin(current, el)\n return () => {\n appliedRef.current?.revert()\n appliedRef.current = null\n }\n }, [current, target])\n\n return <IrisSkinContext.Provider value={{ engine, current }}>{children}</IrisSkinContext.Provider>\n}\n\nexport function useSkinContext(): IrisSkinContextValue {\n const ctx = useContext(IrisSkinContext)\n if (!ctx) throw new Error('[iris-ui] useSkin(): no <SkinProvider> ancestor found')\n return ctx\n}\n\n/** Non-throwing read for skin-aware primitives that may render standalone. */\nexport function useSkinOptional(): ResolvedSkin | undefined {\n return useContext(IrisSkinContext)?.current\n}\n","import * as React from 'react'\nimport type { I18n } from '@iris-ui-kit/core'\n\n/** Carries the active {@link I18n} instance to descendants via `useI18n`. */\nexport const I18nContext = React.createContext<I18n | null>(null)\n","import * as React from 'react'\nimport { createI18n, localeDirection, type I18n, type I18nMessages } from '@iris-ui-kit/core'\nimport { applyDirection } from '@iris-ui-kit/theme'\nimport { I18nContext } from './context'\n\nexport interface IrisI18nProviderProps {\n /** BCP-47 locale. Changes are synced to the live instance. */\n locale?: string\n /** Message overrides. Changes are merged into the live instance. */\n messages?: I18nMessages\n /** Provide a pre-created instance instead of `locale` / `messages`. */\n i18n?: I18n\n /**\n * When set, the locale's writing direction ({@link localeDirection}) is\n * applied to `directionTarget` (`dir` + `data-iris-dir`) and `<html lang>` is\n * set whenever `locale` changes — so \"set locale → flip direction + announce\n * language\" needs no manual wiring. Off by default so it never fights an\n * explicit `<ThemeProvider dir>`. Reverts on unmount.\n */\n autoDirection?: boolean\n /** Element to receive dir/lang when `autoDirection` is set. Defaults to `document.documentElement`. */\n directionTarget?: HTMLElement | null\n children?: React.ReactNode\n}\n\n/**\n * Makes a locale + message dictionary available to descendant components via\n * `useI18n`. Either pass `locale` / `messages` (an instance is created and\n * kept in sync) or a pre-built `i18n` instance you control externally.\n */\nexport function IrisI18nProvider({\n locale,\n messages,\n i18n,\n autoDirection,\n directionTarget,\n children,\n}: IrisI18nProviderProps) {\n const ref = React.useRef<I18n | null>(null)\n if (ref.current === null) {\n ref.current = i18n ?? createI18n({ locale, messages })\n }\n const instance = ref.current\n\n React.useEffect(() => {\n if (i18n || !locale) return\n instance.setLocale(locale)\n }, [locale, i18n, instance])\n\n React.useEffect(() => {\n if (i18n || !messages) return\n instance.setMessages(messages)\n }, [messages, i18n, instance])\n\n // Auto-apply writing direction + `lang` from the active locale (opt-in).\n React.useEffect(() => {\n if (!autoDirection || !locale || typeof document === 'undefined') return\n const el = directionTarget ?? document.documentElement\n const applied = applyDirection(localeDirection(locale), el)\n const prevLang = el.getAttribute('lang')\n el.setAttribute('lang', locale)\n return () => {\n applied.revert()\n if (prevLang === null) el.removeAttribute('lang')\n else el.setAttribute('lang', prevLang)\n }\n }, [autoDirection, locale, directionTarget])\n\n return <I18nContext.Provider value={instance}>{children}</I18nContext.Provider>\n}\n","import { createContext } from 'react'\n\n/**\n * What `<IrisProvider>` hands to descendants: the eagerly-built plugin stores\n * (keyed by registration name) plus the set of installed plugin names.\n *\n * Named `*Context` so the manifest's discover step EXCLUDES it — only\n * `Iris*`-prefixed, non-`Context` exports become manifest components.\n */\nexport interface PluginStoreContextValue {\n stores: Map<string, unknown>\n installed: Set<string>\n}\n\nexport const PluginStoreContext = createContext<PluginStoreContextValue | null>(null)\n","import { useContext, useEffect, useMemo, useRef, type ReactNode } from 'react'\nimport { runPlugins, type IrisPlugin } from '@iris-ui-kit/core'\nimport {\n applyCssVars,\n type ApplyCssVarsResult,\n type Direction,\n type ThemeStore,\n} from '@iris-ui-kit/theme'\nimport type { SkinEngine } from '@iris-ui-kit/skins'\nimport { ThemeProvider } from '../theme'\nimport { SkinProvider } from '../skins'\nimport { IrisI18nProvider } from '../i18n'\nimport { PluginStoreContext } from './context'\n\nexport interface IrisProviderProps {\n /** Active theme store. When passed, wraps children in `<ThemeProvider>`. */\n theme?: ThemeStore\n /** Active skin engine. When passed, wraps children in `<SkinProvider>`. */\n skin?: SkinEngine\n /** Writing direction; forwarded to `<ThemeProvider>`. Default `'ltr'`. */\n dir?: Direction\n /** BCP-47 locale; selects which plugin message slice is applied. */\n locale?: string\n /** User message overrides — these WIN over plugin-registered messages. */\n messages?: Record<string, string>\n /** Plugins to install. Their tokens / messages / stores are collected once. */\n plugins?: IrisPlugin[]\n /** Element to receive plugin tokens. Defaults to `document.documentElement`. */\n target?: HTMLElement | null\n children?: ReactNode\n}\n\n/**\n * The single unified entry point. Runs the plugins, applies their additive\n * token layer over the active theme, merges their messages under the user's,\n * and exposes their stores via `PluginStoreContext`. The existing\n * Theme / Skin / I18n providers are composed in around it.\n *\n * **Zero business logic** — `runPlugins` / `applyCssVars` do the work; this is a\n * thin React bridge. Client boundary (tsup prepends `'use client'`).\n */\nexport function IrisProvider({\n theme,\n skin,\n dir = 'ltr',\n locale,\n messages,\n plugins,\n target = null,\n children,\n}: IrisProviderProps) {\n const collected = useMemo(() => runPlugins(plugins ?? []), [plugins])\n const appliedRef = useRef<ApplyCssVarsResult | null>(null)\n\n useEffect(() => {\n if (typeof document === 'undefined') return\n const el = target ?? document.documentElement\n appliedRef.current?.revert()\n appliedRef.current = applyCssVars(Object.entries(collected.tokens), el)\n return () => {\n appliedRef.current?.revert()\n appliedRef.current = null\n }\n }, [collected, target])\n\n // Run plugin teardowns when the plugins set is swapped (a new `collected`) or\n // on unmount, so eager stores / subscriptions / timers don't leak.\n useEffect(() => () => collected.teardown(), [collected])\n\n const value = useMemo(\n () => ({ stores: collected.stores, installed: new Set((plugins ?? []).map((p) => p.name)) }),\n [collected, plugins],\n )\n\n // Plugin messages are the BASE; user-supplied messages win.\n const merged = { ...collected.messages[locale ?? 'en-US'], ...(messages ?? {}) }\n\n // Order (innermost-out): Theme → Skin → I18n → PluginContext → children.\n let tree: ReactNode = (\n <IrisI18nProvider locale={locale} messages={merged}>\n <PluginStoreContext.Provider value={value}>{children}</PluginStoreContext.Provider>\n </IrisI18nProvider>\n )\n if (skin) {\n tree = (\n <SkinProvider engine={skin} target={target}>\n {tree}\n </SkinProvider>\n )\n }\n if (theme) {\n tree = (\n <ThemeProvider store={theme} dir={dir} target={target}>\n {tree}\n </ThemeProvider>\n )\n }\n return tree\n}\n\n/** Whether a plugin with `name` is installed under the nearest `<IrisProvider>`. */\nexport function usePlugin(name: string): boolean {\n return useContext(PluginStoreContext)?.installed.has(name) ?? false\n}\n\n// Tracks ambiguous store key warnings to avoid spamming the console.\n// Hoisted BEFORE overload signatures (TS requires overloads immediately before implementation).\nconst warnedKeys = new Map<string, boolean>()\n\n/**\n * Read a plugin-registered store by `key` (backward-compatible single-arg form).\n * Falls back to `{namespace}::{key}` lookup if bare key not found.\n * Throws a clear error when there is no `<IrisProvider>` ancestor.\n * Plugins export typed wrappers narrowing `T`.\n */\nexport function usePluginStore<T>(key: string): T\n\n/**\n * Read a plugin-registered store by `namespace` + `key`.\n * Equivalent to `usePluginStore('{namespace}::{key}')`.\n */\nexport function usePluginStore<T>(namespace: string, key: string): T\n\nexport function usePluginStore<T>(nsOrKey: string, key?: string): T {\n const ctx = useContext(PluginStoreContext)\n if (!ctx) {\n const displayKey = key !== undefined ? `${nsOrKey}::${key}` : nsOrKey\n throw new Error(`[iris-ui] usePluginStore(\"${displayKey}\"): no <IrisProvider> ancestor found`)\n }\n\n const fullKey = key !== undefined ? `${nsOrKey}::${key}` : nsOrKey\n\n // 1. Direct lookup using the constructed key\n let store = ctx.stores.get(fullKey) as T | undefined\n if (store !== undefined) return store\n\n // 2. Single-arg: try without namespace first (backward compat for unnamespaced plugins)\n if (key === undefined) {\n // Try the key as a bare key (for plugins without namespace)\n store = ctx.stores.get(nsOrKey) as T | undefined\n if (store !== undefined) return store\n\n // Try as {namespace}::{key} where namespace may equal the key segment\n // e.g. usePluginStore('settings') → try 'default::settings', 'editor::settings', etc.\n // This handles plugins where namespace === name (the common case).\n for (const k of ctx.stores.keys()) {\n if (typeof k === 'string' && k.endsWith(`::${nsOrKey}`)) {\n // Warn at most once per ambiguous key.\n if (!warnedKeys.has(nsOrKey)) {\n warnedKeys.set(nsOrKey, true)\n console.warn(\n `[iris-ui] Ambiguous plugin store key \"${nsOrKey}\". ` +\n `Found \"${k}\". Use the namespaced form for clarity: ` +\n `usePluginStore(\"${k}\").`,\n )\n }\n return ctx.stores.get(k) as T\n }\n }\n }\n\n throw new Error(\n `[iris-ui] Plugin store \"${fullKey}\" not found. ` +\n `Ensure the plugin is installed in IrisProvider and the key is correct.`,\n )\n}\n"]}
@@ -0,0 +1,62 @@
1
+ import * as React from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { IrisPlugin } from '@iris-ui-kit/core';
4
+ import { ThemeStore, Direction } from '@iris-ui-kit/theme';
5
+ import { SkinEngine } from '@iris-ui-kit/skins';
6
+
7
+ interface IrisProviderProps {
8
+ /** Active theme store. When passed, wraps children in `<ThemeProvider>`. */
9
+ theme?: ThemeStore;
10
+ /** Active skin engine. When passed, wraps children in `<SkinProvider>`. */
11
+ skin?: SkinEngine;
12
+ /** Writing direction; forwarded to `<ThemeProvider>`. Default `'ltr'`. */
13
+ dir?: Direction;
14
+ /** BCP-47 locale; selects which plugin message slice is applied. */
15
+ locale?: string;
16
+ /** User message overrides — these WIN over plugin-registered messages. */
17
+ messages?: Record<string, string>;
18
+ /** Plugins to install. Their tokens / messages / stores are collected once. */
19
+ plugins?: IrisPlugin[];
20
+ /** Element to receive plugin tokens. Defaults to `document.documentElement`. */
21
+ target?: HTMLElement | null;
22
+ children?: ReactNode;
23
+ }
24
+ /**
25
+ * The single unified entry point. Runs the plugins, applies their additive
26
+ * token layer over the active theme, merges their messages under the user's,
27
+ * and exposes their stores via `PluginStoreContext`. The existing
28
+ * Theme / Skin / I18n providers are composed in around it.
29
+ *
30
+ * **Zero business logic** — `runPlugins` / `applyCssVars` do the work; this is a
31
+ * thin React bridge. Client boundary (tsup prepends `'use client'`).
32
+ */
33
+ declare function IrisProvider({ theme, skin, dir, locale, messages, plugins, target, children, }: IrisProviderProps): React.ReactElement<any, string | React.JSXElementConstructor<any>>;
34
+ /** Whether a plugin with `name` is installed under the nearest `<IrisProvider>`. */
35
+ declare function usePlugin(name: string): boolean;
36
+ /**
37
+ * Read a plugin-registered store by `key` (backward-compatible single-arg form).
38
+ * Falls back to `{namespace}::{key}` lookup if bare key not found.
39
+ * Throws a clear error when there is no `<IrisProvider>` ancestor.
40
+ * Plugins export typed wrappers narrowing `T`.
41
+ */
42
+ declare function usePluginStore<T>(key: string): T;
43
+ /**
44
+ * Read a plugin-registered store by `namespace` + `key`.
45
+ * Equivalent to `usePluginStore('{namespace}::{key}')`.
46
+ */
47
+ declare function usePluginStore<T>(namespace: string, key: string): T;
48
+
49
+ /**
50
+ * What `<IrisProvider>` hands to descendants: the eagerly-built plugin stores
51
+ * (keyed by registration name) plus the set of installed plugin names.
52
+ *
53
+ * Named `*Context` so the manifest's discover step EXCLUDES it — only
54
+ * `Iris*`-prefixed, non-`Context` exports become manifest components.
55
+ */
56
+ interface PluginStoreContextValue {
57
+ stores: Map<string, unknown>;
58
+ installed: Set<string>;
59
+ }
60
+ declare const PluginStoreContext: React.Context<PluginStoreContextValue | null>;
61
+
62
+ export { IrisProvider, type IrisProviderProps, PluginStoreContext, type PluginStoreContextValue, usePlugin, usePluginStore };
@@ -0,0 +1,62 @@
1
+ import * as React from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { IrisPlugin } from '@iris-ui-kit/core';
4
+ import { ThemeStore, Direction } from '@iris-ui-kit/theme';
5
+ import { SkinEngine } from '@iris-ui-kit/skins';
6
+
7
+ interface IrisProviderProps {
8
+ /** Active theme store. When passed, wraps children in `<ThemeProvider>`. */
9
+ theme?: ThemeStore;
10
+ /** Active skin engine. When passed, wraps children in `<SkinProvider>`. */
11
+ skin?: SkinEngine;
12
+ /** Writing direction; forwarded to `<ThemeProvider>`. Default `'ltr'`. */
13
+ dir?: Direction;
14
+ /** BCP-47 locale; selects which plugin message slice is applied. */
15
+ locale?: string;
16
+ /** User message overrides — these WIN over plugin-registered messages. */
17
+ messages?: Record<string, string>;
18
+ /** Plugins to install. Their tokens / messages / stores are collected once. */
19
+ plugins?: IrisPlugin[];
20
+ /** Element to receive plugin tokens. Defaults to `document.documentElement`. */
21
+ target?: HTMLElement | null;
22
+ children?: ReactNode;
23
+ }
24
+ /**
25
+ * The single unified entry point. Runs the plugins, applies their additive
26
+ * token layer over the active theme, merges their messages under the user's,
27
+ * and exposes their stores via `PluginStoreContext`. The existing
28
+ * Theme / Skin / I18n providers are composed in around it.
29
+ *
30
+ * **Zero business logic** — `runPlugins` / `applyCssVars` do the work; this is a
31
+ * thin React bridge. Client boundary (tsup prepends `'use client'`).
32
+ */
33
+ declare function IrisProvider({ theme, skin, dir, locale, messages, plugins, target, children, }: IrisProviderProps): React.ReactElement<any, string | React.JSXElementConstructor<any>>;
34
+ /** Whether a plugin with `name` is installed under the nearest `<IrisProvider>`. */
35
+ declare function usePlugin(name: string): boolean;
36
+ /**
37
+ * Read a plugin-registered store by `key` (backward-compatible single-arg form).
38
+ * Falls back to `{namespace}::{key}` lookup if bare key not found.
39
+ * Throws a clear error when there is no `<IrisProvider>` ancestor.
40
+ * Plugins export typed wrappers narrowing `T`.
41
+ */
42
+ declare function usePluginStore<T>(key: string): T;
43
+ /**
44
+ * Read a plugin-registered store by `namespace` + `key`.
45
+ * Equivalent to `usePluginStore('{namespace}::{key}')`.
46
+ */
47
+ declare function usePluginStore<T>(namespace: string, key: string): T;
48
+
49
+ /**
50
+ * What `<IrisProvider>` hands to descendants: the eagerly-built plugin stores
51
+ * (keyed by registration name) plus the set of installed plugin names.
52
+ *
53
+ * Named `*Context` so the manifest's discover step EXCLUDES it — only
54
+ * `Iris*`-prefixed, non-`Context` exports become manifest components.
55
+ */
56
+ interface PluginStoreContextValue {
57
+ stores: Map<string, unknown>;
58
+ installed: Set<string>;
59
+ }
60
+ declare const PluginStoreContext: React.Context<PluginStoreContextValue | null>;
61
+
62
+ export { IrisProvider, type IrisProviderProps, PluginStoreContext, type PluginStoreContextValue, usePlugin, usePluginStore };
@@ -0,0 +1,8 @@
1
+ 'use client'
2
+ export { IrisProvider, PluginStoreContext, usePlugin, usePluginStore } from './chunk-IDD35UJ6.js';
3
+ import './chunk-WIHBIDVJ.js';
4
+ import './chunk-XCK4RIXB.js';
5
+ import './chunk-OMOTUHYI.js';
6
+ import './chunk-RZNYIFV2.js';
7
+ //# sourceMappingURL=provider.js.map
8
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":";","file":"provider.js"}
@@ -0,0 +1,61 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ var React2 = require('react');
5
+ var core = require('@iris-ui-kit/core');
6
+
7
+ function _interopNamespace(e) {
8
+ if (e && e.__esModule) return e;
9
+ var n = Object.create(null);
10
+ if (e) {
11
+ Object.keys(e).forEach(function (k) {
12
+ if (k !== 'default') {
13
+ var d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: function () { return e[k]; }
17
+ });
18
+ }
19
+ });
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+
25
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
26
+
27
+ // src/resource/useResourceController.ts
28
+ function useStore(store) {
29
+ return React2.useSyncExternalStore(
30
+ store.subscribe,
31
+ store.getState,
32
+ store.getState
33
+ // SSR fallback — same as client snapshot in our case.
34
+ );
35
+ }
36
+
37
+ // src/resource/useResourceController.ts
38
+ function useResourceController(config) {
39
+ const ref = React2__namespace.useRef(null);
40
+ if (ref.current === null) ref.current = core.createResourceController({ ...config, immediate: false });
41
+ const controller = ref.current;
42
+ const immediate = config.immediate !== false;
43
+ React2__namespace.useEffect(() => {
44
+ if (immediate) void controller.load();
45
+ return () => controller.destroy();
46
+ }, [controller, immediate]);
47
+ const state = useStore(controller.store);
48
+ return React2__namespace.useMemo(() => ({ ...controller, state }), [controller, state]);
49
+ }
50
+
51
+ Object.defineProperty(exports, "createClientFetcher", {
52
+ enumerable: true,
53
+ get: function () { return core.createClientFetcher; }
54
+ });
55
+ Object.defineProperty(exports, "createResourceController", {
56
+ enumerable: true,
57
+ get: function () { return core.createResourceController; }
58
+ });
59
+ exports.useResourceController = useResourceController;
60
+ //# sourceMappingURL=resource.cjs.map
61
+ //# sourceMappingURL=resource.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/useStore.ts","../src/resource/useResourceController.ts"],"names":["useSyncExternalStore","React2","createResourceController"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAUO,SAAS,SAAY,KAAA,EAA4B;AACtD,EAAA,OAAOA,2BAAA;AAAA,IACL,KAAA,CAAM,SAAA;AAAA,IACN,KAAA,CAAM,QAAA;AAAA,IACN,KAAA,CAAM;AAAA;AAAA,GACR;AACF;;;ACSO,SAAS,sBACd,MAAA,EAC0B;AAC1B,EAAA,MAAM,GAAA,GAAYC,yBAAqC,IAAI,CAAA;AAC3D,EAAA,IAAI,GAAA,CAAI,OAAA,KAAY,IAAA,EAAM,GAAA,CAAI,OAAA,GAAUC,6BAAA,CAAyB,EAAE,GAAG,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAO,CAAA;AAChG,EAAA,MAAM,aAAa,GAAA,CAAI,OAAA;AACvB,EAAA,MAAM,SAAA,GAAY,OAAO,SAAA,KAAc,KAAA;AAIvC,EAAMD,4BAAU,MAAM;AACpB,IAAA,IAAI,SAAA,EAAW,KAAK,UAAA,CAAW,IAAA,EAAK;AACpC,IAAA,OAAO,MAAM,WAAW,OAAA,EAAQ;AAAA,EAClC,CAAA,EAAG,CAAC,UAAA,EAAY,SAAS,CAAC,CAAA;AAE1B,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AACvC,EAAA,OAAaA,iBAAA,CAAA,OAAA,CAAQ,OAAO,EAAE,GAAG,UAAA,EAAY,OAAM,CAAA,EAAI,CAAC,UAAA,EAAY,KAAK,CAAC,CAAA;AAC5E","file":"resource.cjs","sourcesContent":["import * as React from 'react'\nimport { useSyncExternalStore } from 'react'\nimport type { ReadonlyStore, Store } from '@iris-ui-kit/core'\n\n/**\n * Bridge a framework-agnostic `@iris-ui-kit/core` store into React reactivity.\n * Uses React 18's `useSyncExternalStore` — the contract is identical to the\n * one Vue uses via `ref + onMounted` and Solid uses via `createSignal`. The\n * **same** store can power Button, Popover, Dialog, etc. on any framework.\n */\nexport function useStore<T>(store: ReadonlyStore<T>): T {\n return useSyncExternalStore(\n store.subscribe,\n store.getState,\n store.getState, // SSR fallback — same as client snapshot in our case.\n )\n}\n\n/**\n * Subscribe to a DERIVED slice of a core store — the component re-renders only\n * when `selector(state)` changes per `isEqual` (default `Object.is`), not on\n * every store emission. Built on {@link Store.subscribeWith}. Inline closures\n * for `selector`/`isEqual` are fine (captured via refs; the subscription is not\n * re-created between renders).\n */\nexport function useStoreSelector<T, U>(\n store: Store<T>,\n selector: (state: T) => U,\n isEqual?: (a: U, b: U) => boolean,\n): U {\n const [slice, setSlice] = React.useState(() => selector(store.getState()))\n const selRef = React.useRef(selector)\n selRef.current = selector\n const eqRef = React.useRef(isEqual)\n eqRef.current = isEqual\n React.useEffect(() => {\n const read = (s: T): U => selRef.current(s)\n const eq = (a: U, b: U): boolean => (eqRef.current ?? Object.is)(a, b)\n // Re-sync in case the store moved between render and this effect.\n setSlice((prev) => {\n const next = read(store.getState())\n return eq(prev, next) ? prev : next\n })\n return store.subscribeWith(read, setSlice, eq)\n }, [store])\n return slice\n}\n","import * as React from 'react'\nimport {\n createResourceController,\n type ResourceController,\n type ResourceControllerConfig,\n type ResourceState,\n} from '@iris-ui-kit/core'\nimport { useStore } from '../useStore'\n\nexport interface UseResourceController<T> extends ResourceController<T> {\n /** The live resource state (rows, total, page, loading, selectedKeys). */\n state: ResourceState<T>\n}\n\n/**\n * React bridge over the framework-agnostic {@link createResourceController} (L4\n * CRUD list composite). Creates the controller once, subscribes to its store,\n * and returns the controller plus its live `state`. A thin bridge — all logic\n * lives in `@iris-ui-kit/core`.\n *\n * The controller is constructed with `immediate: false` so no fetch fires during\n * React's (side-effect-free) render phase; the initial load is kicked from an\n * effect instead, and the controller is torn down on unmount so an in-flight\n * request never writes back to an unmounted component.\n */\nexport function useResourceController<T>(\n config: ResourceControllerConfig<T>,\n): UseResourceController<T> {\n const ref = React.useRef<ResourceController<T> | null>(null)\n if (ref.current === null) ref.current = createResourceController({ ...config, immediate: false })\n const controller = ref.current\n const immediate = config.immediate !== false\n\n // Construct-once controller: load on mount (when immediate) + tear down on\n // unmount. `immediate` is captured at mount; it is not a reactive dependency.\n React.useEffect(() => {\n if (immediate) void controller.load()\n return () => controller.destroy()\n }, [controller, immediate])\n\n const state = useStore(controller.store)\n return React.useMemo(() => ({ ...controller, state }), [controller, state])\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import { ResourceController, ResourceState, ResourceControllerConfig } from '@iris-ui-kit/core';
2
+ export { DataViewColumn, MutateOptions, ResourceController, ResourceControllerConfig, ResourceQuery, ResourceState, createClientFetcher, createResourceController } from '@iris-ui-kit/core';
3
+
4
+ interface UseResourceController<T> extends ResourceController<T> {
5
+ /** The live resource state (rows, total, page, loading, selectedKeys). */
6
+ state: ResourceState<T>;
7
+ }
8
+ /**
9
+ * React bridge over the framework-agnostic {@link createResourceController} (L4
10
+ * CRUD list composite). Creates the controller once, subscribes to its store,
11
+ * and returns the controller plus its live `state`. A thin bridge — all logic
12
+ * lives in `@iris-ui-kit/core`.
13
+ *
14
+ * The controller is constructed with `immediate: false` so no fetch fires during
15
+ * React's (side-effect-free) render phase; the initial load is kicked from an
16
+ * effect instead, and the controller is torn down on unmount so an in-flight
17
+ * request never writes back to an unmounted component.
18
+ */
19
+ declare function useResourceController<T>(config: ResourceControllerConfig<T>): UseResourceController<T>;
20
+
21
+ export { type UseResourceController, useResourceController };
@@ -0,0 +1,21 @@
1
+ import { ResourceController, ResourceState, ResourceControllerConfig } from '@iris-ui-kit/core';
2
+ export { DataViewColumn, MutateOptions, ResourceController, ResourceControllerConfig, ResourceQuery, ResourceState, createClientFetcher, createResourceController } from '@iris-ui-kit/core';
3
+
4
+ interface UseResourceController<T> extends ResourceController<T> {
5
+ /** The live resource state (rows, total, page, loading, selectedKeys). */
6
+ state: ResourceState<T>;
7
+ }
8
+ /**
9
+ * React bridge over the framework-agnostic {@link createResourceController} (L4
10
+ * CRUD list composite). Creates the controller once, subscribes to its store,
11
+ * and returns the controller plus its live `state`. A thin bridge — all logic
12
+ * lives in `@iris-ui-kit/core`.
13
+ *
14
+ * The controller is constructed with `immediate: false` so no fetch fires during
15
+ * React's (side-effect-free) render phase; the initial load is kicked from an
16
+ * effect instead, and the controller is torn down on unmount so an in-flight
17
+ * request never writes back to an unmounted component.
18
+ */
19
+ declare function useResourceController<T>(config: ResourceControllerConfig<T>): UseResourceController<T>;
20
+
21
+ export { type UseResourceController, useResourceController };
@@ -0,0 +1,5 @@
1
+ 'use client'
2
+ export { createClientFetcher, createResourceController, useResourceController } from './chunk-TQ33XJIK.js';
3
+ import './chunk-RZNYIFV2.js';
4
+ //# sourceMappingURL=resource.js.map
5
+ //# sourceMappingURL=resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":";","file":"resource.js"}