@iris-ui-kit/vue 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.
- package/LICENSE +21 -0
- package/dist/admin.cjs +1869 -0
- package/dist/admin.cjs.map +1 -0
- package/dist/admin.d.cts +376 -0
- package/dist/admin.d.ts +376 -0
- package/dist/admin.js +10 -0
- package/dist/admin.js.map +1 -0
- package/dist/async.cjs +76 -0
- package/dist/async.cjs.map +1 -0
- package/dist/async.d.cts +59 -0
- package/dist/async.d.ts +59 -0
- package/dist/async.js +3 -0
- package/dist/async.js.map +1 -0
- package/dist/behaviors.cjs +659 -0
- package/dist/behaviors.cjs.map +1 -0
- package/dist/behaviors.d.cts +441 -0
- package/dist/behaviors.d.ts +441 -0
- package/dist/behaviors.js +3 -0
- package/dist/behaviors.js.map +1 -0
- package/dist/chunk-3FJUCHCC.js +146 -0
- package/dist/chunk-3FJUCHCC.js.map +1 -0
- package/dist/chunk-3R3QDLJC.js +172 -0
- package/dist/chunk-3R3QDLJC.js.map +1 -0
- package/dist/chunk-4FLIW67H.js +137 -0
- package/dist/chunk-4FLIW67H.js.map +1 -0
- package/dist/chunk-4FQ7XF52.js +3 -0
- package/dist/chunk-4FQ7XF52.js.map +1 -0
- package/dist/chunk-72PZMU6R.js +99 -0
- package/dist/chunk-72PZMU6R.js.map +1 -0
- package/dist/chunk-75GSYEJS.js +17 -0
- package/dist/chunk-75GSYEJS.js.map +1 -0
- package/dist/chunk-7IOJADZC.js +38 -0
- package/dist/chunk-7IOJADZC.js.map +1 -0
- package/dist/chunk-CIZGSGXN.js +651 -0
- package/dist/chunk-CIZGSGXN.js.map +1 -0
- package/dist/chunk-F77KIPOH.js +103 -0
- package/dist/chunk-F77KIPOH.js.map +1 -0
- package/dist/chunk-FJBYAIL4.js +1318 -0
- package/dist/chunk-FJBYAIL4.js.map +1 -0
- package/dist/chunk-H7HVVPYR.js +66 -0
- package/dist/chunk-H7HVVPYR.js.map +1 -0
- package/dist/chunk-I6D5VXQK.js +167 -0
- package/dist/chunk-I6D5VXQK.js.map +1 -0
- package/dist/chunk-PPYNXNGZ.js +73 -0
- package/dist/chunk-PPYNXNGZ.js.map +1 -0
- package/dist/chunk-QLUIKEMJ.js +1197 -0
- package/dist/chunk-QLUIKEMJ.js.map +1 -0
- package/dist/chunk-ROJV6RON.js +3 -0
- package/dist/chunk-ROJV6RON.js.map +1 -0
- package/dist/chunk-S43IHHBU.js +82 -0
- package/dist/chunk-S43IHHBU.js.map +1 -0
- package/dist/chunk-TCAXRWT6.js +108 -0
- package/dist/chunk-TCAXRWT6.js.map +1 -0
- package/dist/chunk-TQB5LVOH.js +17 -0
- package/dist/chunk-TQB5LVOH.js.map +1 -0
- package/dist/chunk-VM2CXEUA.js +46 -0
- package/dist/chunk-VM2CXEUA.js.map +1 -0
- package/dist/chunk-W2JVHGFR.js +103 -0
- package/dist/chunk-W2JVHGFR.js.map +1 -0
- package/dist/chunk-WL67XCH5.js +59 -0
- package/dist/chunk-WL67XCH5.js.map +1 -0
- package/dist/chunk-XCNCIG2I.js +165 -0
- package/dist/chunk-XCNCIG2I.js.map +1 -0
- package/dist/chunk-XSLBANUV.js +16 -0
- package/dist/chunk-XSLBANUV.js.map +1 -0
- package/dist/chunk-ZY4NLITM.js +73 -0
- package/dist/chunk-ZY4NLITM.js.map +1 -0
- package/dist/data.cjs +59 -0
- package/dist/data.cjs.map +1 -0
- package/dist/data.d.cts +46 -0
- package/dist/data.d.ts +46 -0
- package/dist/data.js +4 -0
- package/dist/data.js.map +1 -0
- package/dist/error-boundary.cjs +115 -0
- package/dist/error-boundary.cjs.map +1 -0
- package/dist/error-boundary.d.cts +60 -0
- package/dist/error-boundary.d.ts +60 -0
- package/dist/error-boundary.js +4 -0
- package/dist/error-boundary.js.map +1 -0
- package/dist/floating.cjs +149 -0
- package/dist/floating.cjs.map +1 -0
- package/dist/floating.d.cts +106 -0
- package/dist/floating.d.ts +106 -0
- package/dist/floating.js +4 -0
- package/dist/floating.js.map +1 -0
- package/dist/form.cjs +144 -0
- package/dist/form.cjs.map +1 -0
- package/dist/form.d.cts +128 -0
- package/dist/form.d.ts +128 -0
- package/dist/form.js +3 -0
- package/dist/form.js.map +1 -0
- package/dist/i18n.cjs +112 -0
- package/dist/i18n.cjs.map +1 -0
- package/dist/i18n.d.cts +99 -0
- package/dist/i18n.d.ts +99 -0
- package/dist/i18n.js +3 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.cjs +18673 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +8087 -0
- package/dist/index.d.ts +8087 -0
- package/dist/index.js +13525 -0
- package/dist/index.js.map +1 -0
- package/dist/layouts.cjs +392 -0
- package/dist/layouts.cjs.map +1 -0
- package/dist/layouts.d.cts +406 -0
- package/dist/layouts.d.ts +406 -0
- package/dist/layouts.js +5 -0
- package/dist/layouts.js.map +1 -0
- package/dist/machine.cjs +19 -0
- package/dist/machine.cjs.map +1 -0
- package/dist/machine.d.cts +18 -0
- package/dist/machine.d.ts +18 -0
- package/dist/machine.js +4 -0
- package/dist/machine.js.map +1 -0
- package/dist/modal-utils.cjs +170 -0
- package/dist/modal-utils.cjs.map +1 -0
- package/dist/modal-utils.d.cts +43 -0
- package/dist/modal-utils.d.ts +43 -0
- package/dist/modal-utils.js +3 -0
- package/dist/modal-utils.js.map +1 -0
- package/dist/motion.cjs +88 -0
- package/dist/motion.cjs.map +1 -0
- package/dist/motion.d.cts +43 -0
- package/dist/motion.d.ts +43 -0
- package/dist/motion.js +3 -0
- package/dist/motion.js.map +1 -0
- package/dist/provider.cjs +272 -0
- package/dist/provider.cjs.map +1 -0
- package/dist/provider.d.cts +130 -0
- package/dist/provider.d.ts +130 -0
- package/dist/provider.js +6 -0
- package/dist/provider.js.map +1 -0
- package/dist/resource.cjs +25 -0
- package/dist/resource.cjs.map +1 -0
- package/dist/resource.d.cts +17 -0
- package/dist/resource.d.ts +17 -0
- package/dist/resource.js +3 -0
- package/dist/resource.js.map +1 -0
- package/dist/skeletons.cjs +1659 -0
- package/dist/skeletons.cjs.map +1 -0
- package/dist/skeletons.d.cts +179 -0
- package/dist/skeletons.d.ts +179 -0
- package/dist/skeletons.js +7 -0
- package/dist/skeletons.js.map +1 -0
- package/dist/skins.cjs +138 -0
- package/dist/skins.cjs.map +1 -0
- package/dist/skins.d.cts +67 -0
- package/dist/skins.d.ts +67 -0
- package/dist/skins.js +3 -0
- package/dist/skins.js.map +1 -0
- package/dist/theme.cjs +106 -0
- package/dist/theme.cjs.map +1 -0
- package/dist/theme.d.cts +103 -0
- package/dist/theme.d.ts +103 -0
- package/dist/theme.js +3 -0
- package/dist/theme.js.map +1 -0
- package/dist/undo.cjs +51 -0
- package/dist/undo.cjs.map +1 -0
- package/dist/undo.d.cts +48 -0
- package/dist/undo.d.ts +48 -0
- package/dist/undo.js +3 -0
- package/dist/undo.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { SkinProvider } from './chunk-H7HVVPYR.js';
|
|
2
|
+
import { ThemeProvider } from './chunk-72PZMU6R.js';
|
|
3
|
+
import { IrisI18nProvider } from './chunk-TCAXRWT6.js';
|
|
4
|
+
import { defineComponent, onMounted, onBeforeUnmount, provide, h, inject } from 'vue';
|
|
5
|
+
import { runPlugins } from '@iris-ui-kit/core';
|
|
6
|
+
import { applyCssVars } from '@iris-ui-kit/theme';
|
|
7
|
+
|
|
8
|
+
// src/provider/context.ts
|
|
9
|
+
var PluginStoreContextKey = /* @__PURE__ */ Symbol("IrisPluginStore");
|
|
10
|
+
|
|
11
|
+
// src/provider/IrisProvider.ts
|
|
12
|
+
var DEFAULT_LOCALE = "en-US";
|
|
13
|
+
var IrisProvider = defineComponent({
|
|
14
|
+
name: "IrisProvider",
|
|
15
|
+
props: {
|
|
16
|
+
theme: { type: Object, default: void 0 },
|
|
17
|
+
skin: { type: Object, default: void 0 },
|
|
18
|
+
dir: { type: String, default: void 0 },
|
|
19
|
+
locale: { type: String, default: void 0 },
|
|
20
|
+
messages: { type: Object, default: void 0 },
|
|
21
|
+
plugins: { type: Array, default: void 0 },
|
|
22
|
+
target: { type: Object, default: null }
|
|
23
|
+
},
|
|
24
|
+
setup(props, { slots }) {
|
|
25
|
+
const collected = runPlugins(props.plugins ?? []);
|
|
26
|
+
let applied = null;
|
|
27
|
+
onMounted(() => {
|
|
28
|
+
if (typeof document === "undefined") return;
|
|
29
|
+
const el = props.target ?? document.documentElement;
|
|
30
|
+
applied = applyCssVars(Object.entries(collected.tokens), el);
|
|
31
|
+
});
|
|
32
|
+
onBeforeUnmount(() => {
|
|
33
|
+
applied?.revert();
|
|
34
|
+
applied = null;
|
|
35
|
+
collected.teardown();
|
|
36
|
+
});
|
|
37
|
+
provide(PluginStoreContextKey, {
|
|
38
|
+
stores: collected.stores,
|
|
39
|
+
installed: new Set((props.plugins ?? []).map((p) => p.name))
|
|
40
|
+
});
|
|
41
|
+
return () => {
|
|
42
|
+
const locale = props.locale ?? DEFAULT_LOCALE;
|
|
43
|
+
const messages = { ...collected.messages[locale], ...props.messages ?? {} };
|
|
44
|
+
let tree = h(
|
|
45
|
+
IrisI18nProvider,
|
|
46
|
+
{ locale: props.locale, messages },
|
|
47
|
+
{ default: () => slots.default?.() }
|
|
48
|
+
);
|
|
49
|
+
if (props.skin) {
|
|
50
|
+
tree = h(
|
|
51
|
+
SkinProvider,
|
|
52
|
+
{ engine: props.skin, target: props.target },
|
|
53
|
+
{ default: () => tree }
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
if (props.theme) {
|
|
57
|
+
tree = h(
|
|
58
|
+
ThemeProvider,
|
|
59
|
+
{ store: props.theme, target: props.target, dir: props.dir ?? "ltr" },
|
|
60
|
+
{ default: () => tree }
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return tree;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
function usePlugin(name) {
|
|
68
|
+
const ctx = inject(PluginStoreContextKey, null);
|
|
69
|
+
return ctx ? ctx.installed.has(name) : false;
|
|
70
|
+
}
|
|
71
|
+
var warnedKeys = /* @__PURE__ */ new Map();
|
|
72
|
+
function usePluginStore(nsOrKey, key) {
|
|
73
|
+
const ctx = inject(PluginStoreContextKey, null);
|
|
74
|
+
if (!ctx) {
|
|
75
|
+
const displayKey = key !== void 0 ? `${nsOrKey}::${key}` : nsOrKey;
|
|
76
|
+
throw new Error(`[iris-ui] usePluginStore("${displayKey}"): no <IrisProvider> ancestor found`);
|
|
77
|
+
}
|
|
78
|
+
const fullKey = key !== void 0 ? `${nsOrKey}::${key}` : nsOrKey;
|
|
79
|
+
let store = ctx.stores.get(fullKey);
|
|
80
|
+
if (store !== void 0) return store;
|
|
81
|
+
if (key === void 0) {
|
|
82
|
+
store = ctx.stores.get(nsOrKey);
|
|
83
|
+
if (store !== void 0) return store;
|
|
84
|
+
for (const k of ctx.stores.keys()) {
|
|
85
|
+
if (typeof k === "string" && k.endsWith(`::${nsOrKey}`)) {
|
|
86
|
+
if (!warnedKeys.has(nsOrKey)) {
|
|
87
|
+
warnedKeys.set(nsOrKey, true);
|
|
88
|
+
console.warn(
|
|
89
|
+
`[iris-ui] Ambiguous plugin store key "${nsOrKey}". Found "${k}". Use the namespaced form: usePluginStore("${k}").`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return ctx.stores.get(k);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
throw new Error(
|
|
97
|
+
`[iris-ui] Plugin store "${fullKey}" not found. Ensure the plugin is installed in IrisProvider and the key is correct.`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { IrisProvider, PluginStoreContextKey, usePlugin, usePluginStore };
|
|
102
|
+
//# sourceMappingURL=chunk-W2JVHGFR.js.map
|
|
103
|
+
//# sourceMappingURL=chunk-W2JVHGFR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider/context.ts","../src/provider/IrisProvider.ts","../src/provider/hooks.ts"],"names":[],"mappings":"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","file":"chunk-W2JVHGFR.js","sourcesContent":["import { type InjectionKey } from 'vue'\n\n/**\n * Shape carried by the plugin-store context: the live store instances collected\n * from every installed plugin, plus the set of installed plugin names. Surfaced\n * to descendants through `usePluginStore` / `usePlugin`.\n */\nexport interface PluginStoreContext {\n stores: Map<string, unknown>\n installed: Set<string>\n}\n\n/**\n * Injection key for the {@link PluginStoreContext}. The name ends in `Key` (and\n * the type in `Context`) so the manifest's discover step never mistakes it for a\n * component export.\n */\nexport const PluginStoreContextKey: InjectionKey<PluginStoreContext> = Symbol('IrisPluginStore')\n","import {\n defineComponent,\n h,\n onBeforeUnmount,\n onMounted,\n provide,\n type PropType,\n type VNode,\n} from 'vue'\nimport { runPlugins, type IrisPlugin } from '@iris-ui-kit/core'\nimport { applyCssVars, type ApplyCssVarsResult, type ThemeStore } 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 { PluginStoreContextKey } from './context'\n\nconst DEFAULT_LOCALE = 'en-US'\n\n/** Public prop surface of {@link IrisProvider}. */\nexport interface IrisProviderProps {\n /** Theme store; when present the inner `ThemeProvider` wraps the subtree. */\n theme?: ThemeStore\n /** Skin engine; when present the inner `SkinProvider` wraps the subtree. */\n skin?: SkinEngine\n /** Writing direction, forwarded to `ThemeProvider` when a theme is given. */\n dir?: 'ltr' | 'rtl'\n /** Active BCP-47 locale; defaults to `'en-US'`. */\n locale?: string\n /** User messages — merged OVER plugin-registered messages (user wins). */\n messages?: Record<string, string>\n /** Plugins to install; their tokens / messages / stores are collected once. */\n plugins?: IrisPlugin[]\n /** Element receiving the plugin token layer; defaults to `documentElement`. */\n target?: HTMLElement | null\n}\n\n/**\n * The single unified Iris entry point. Runs `plugins` through the core\n * `runPlugins` collector and wires the result into the theme (tokens), i18n\n * (messages) and a plugin-store context, composing the existing per-framework\n * providers. A thin bridge — the real logic lives in `@iris-ui-kit/core`.\n *\n * Render order when present: Theme → Skin → I18n → PluginContext → children.\n */\nexport const IrisProvider = defineComponent({\n name: 'IrisProvider',\n props: {\n theme: { type: Object as PropType<ThemeStore>, default: undefined },\n skin: { type: Object as PropType<SkinEngine>, default: undefined },\n dir: { type: String as PropType<'ltr' | 'rtl'>, default: undefined },\n locale: { type: String, default: undefined },\n messages: { type: Object as PropType<Record<string, string>>, default: undefined },\n plugins: { type: Array as PropType<IrisPlugin[]>, default: undefined },\n target: { type: Object as PropType<HTMLElement | null>, default: null },\n },\n setup(props, { slots }) {\n // Sync, pure, deterministic — computed once per setup over `plugins`.\n const collected = runPlugins(props.plugins ?? [])\n\n // tokens → additive CSS-var layer over the active theme; reverted on unmount.\n let applied: ApplyCssVarsResult | null = null\n onMounted(() => {\n if (typeof document === 'undefined') return\n const el = props.target ?? document.documentElement\n applied = applyCssVars(Object.entries(collected.tokens), el)\n })\n onBeforeUnmount(() => {\n applied?.revert()\n applied = null\n // Run plugin teardowns on unmount so eager stores / subscriptions /\n // timers don't leak. Idempotent and safe with no plugins.\n collected.teardown()\n })\n\n // stores + installed names → PluginStoreContext.\n provide(PluginStoreContextKey, {\n stores: collected.stores,\n installed: new Set((props.plugins ?? []).map((p) => p.name)),\n })\n\n return () => {\n const locale = props.locale ?? DEFAULT_LOCALE\n // Plugin messages as BASE, user messages WIN.\n const messages = { ...collected.messages[locale], ...(props.messages ?? {}) }\n\n // I18n always renders, wrapping children.\n let tree: VNode = h(\n IrisI18nProvider,\n { locale: props.locale, messages },\n { default: () => slots.default?.() },\n )\n // Skin wraps only when a `skin` engine is supplied.\n if (props.skin) {\n tree = h(\n SkinProvider,\n { engine: props.skin, target: props.target },\n { default: () => tree },\n )\n }\n // Theme wraps only when a `theme` store is supplied.\n if (props.theme) {\n tree = h(\n ThemeProvider,\n { store: props.theme, target: props.target, dir: props.dir ?? 'ltr' },\n { default: () => tree },\n )\n }\n return tree\n }\n },\n})\n","import { inject } from 'vue'\nimport { PluginStoreContextKey } from './context'\n\n/** Whether the named plugin is installed by the nearest `<IrisProvider>`. */\nexport function usePlugin(name: string): boolean {\n const ctx = inject(PluginStoreContextKey, null)\n return ctx ? ctx.installed.has(name) : false\n}\n\n// Tracks ambiguous store key warnings to avoid spamming the console.\nconst warnedKeys = new Map<string, boolean>()\n\n/**\n * Read a plugin-registered store by `key` (backward-compatible single-arg form).\n * Throws a clear error when used outside an `<IrisProvider>`.\n */\nexport function usePluginStore<T>(key: string): T\n\n/**\n * Read a plugin-registered store by `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 = inject(PluginStoreContextKey, null)\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\n let store = ctx.stores.get(fullKey) as T | undefined\n if (store !== undefined) return store\n\n // 2. Single-arg fallback\n if (key === undefined) {\n store = ctx.stores.get(nsOrKey) as T | undefined\n if (store !== undefined) return store\n\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: 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,59 @@
|
|
|
1
|
+
import { defineComponent, computed, h } from 'vue';
|
|
2
|
+
|
|
3
|
+
// src/layouts/Grid.ts
|
|
4
|
+
function resolveColumns(columns, minColWidth) {
|
|
5
|
+
if (typeof columns === "number") return `repeat(${columns}, minmax(0, 1fr))`;
|
|
6
|
+
if (columns === "auto-fit") return `repeat(auto-fit, minmax(${minColWidth}, 1fr))`;
|
|
7
|
+
if (columns === "auto-fill") return `repeat(auto-fill, minmax(${minColWidth}, 1fr))`;
|
|
8
|
+
return columns;
|
|
9
|
+
}
|
|
10
|
+
function toCssSpacing(spacing) {
|
|
11
|
+
if (typeof spacing === "number") return `${spacing}px`;
|
|
12
|
+
if (spacing === "sm" || spacing === "md" || spacing === "lg") {
|
|
13
|
+
return `var(--iris-gap-${spacing})`;
|
|
14
|
+
}
|
|
15
|
+
return spacing;
|
|
16
|
+
}
|
|
17
|
+
var IrisGrid = defineComponent({
|
|
18
|
+
name: "IrisGrid",
|
|
19
|
+
inheritAttrs: false,
|
|
20
|
+
props: {
|
|
21
|
+
columns: { type: [Number, String], default: "auto-fit" },
|
|
22
|
+
/** Min width per column for `auto-fit` / `auto-fill`. */
|
|
23
|
+
minColWidth: { type: String, default: "200px" },
|
|
24
|
+
/** Row gap (token / px / CSS). */
|
|
25
|
+
rowGap: { type: [String, Number], default: void 0 },
|
|
26
|
+
/** Column gap (token / px / CSS). */
|
|
27
|
+
columnGap: { type: [String, Number], default: void 0 },
|
|
28
|
+
/** Shorthand for both row + column gap. Overridden if rowGap/columnGap given. */
|
|
29
|
+
gap: { type: [String, Number], default: "md" },
|
|
30
|
+
inline: { type: Boolean, default: false }
|
|
31
|
+
},
|
|
32
|
+
setup(props, { slots, attrs }) {
|
|
33
|
+
const style = computed(() => {
|
|
34
|
+
const colTemplate = resolveColumns(props.columns, props.minColWidth);
|
|
35
|
+
const rowGap = props.rowGap !== void 0 ? toCssSpacing(props.rowGap) : toCssSpacing(props.gap);
|
|
36
|
+
const colGap = props.columnGap !== void 0 ? toCssSpacing(props.columnGap) : toCssSpacing(props.gap);
|
|
37
|
+
return {
|
|
38
|
+
display: props.inline ? "inline-grid" : "grid",
|
|
39
|
+
gridTemplateColumns: colTemplate,
|
|
40
|
+
rowGap,
|
|
41
|
+
columnGap: colGap
|
|
42
|
+
};
|
|
43
|
+
});
|
|
44
|
+
return () => h(
|
|
45
|
+
"div",
|
|
46
|
+
{
|
|
47
|
+
...attrs,
|
|
48
|
+
"data-iris-grid": "",
|
|
49
|
+
"data-iris-grid-columns": String(props.columns),
|
|
50
|
+
style: { ...style.value, ...attrs.style ?? {} }
|
|
51
|
+
},
|
|
52
|
+
slots.default?.()
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
export { IrisGrid };
|
|
58
|
+
//# sourceMappingURL=chunk-WL67XCH5.js.map
|
|
59
|
+
//# sourceMappingURL=chunk-WL67XCH5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/layouts/Grid.ts"],"names":[],"mappings":";;;AAQA,SAAS,cAAA,CAAe,SAA0B,WAAA,EAA6B;AAC7E,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,EAAU,OAAO,UAAU,OAAO,CAAA,iBAAA,CAAA;AACzD,EAAA,IAAI,OAAA,KAAY,UAAA,EAAY,OAAO,CAAA,wBAAA,EAA2B,WAAW,CAAA,OAAA,CAAA;AACzE,EAAA,IAAI,OAAA,KAAY,WAAA,EAAa,OAAO,CAAA,yBAAA,EAA4B,WAAW,CAAA,OAAA,CAAA;AAC3E,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,aAAa,OAAA,EAAkC;AACtD,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,EAAU,OAAO,GAAG,OAAO,CAAA,EAAA,CAAA;AAClD,EAAA,IAAI,OAAA,KAAY,IAAA,IAAQ,OAAA,KAAY,IAAA,IAAQ,YAAY,IAAA,EAAM;AAC5D,IAAA,OAAO,kBAAkB,OAAO,CAAA,CAAA,CAAA;AAAA,EAClC;AACA,EAAA,OAAO,OAAA;AACT;AAaO,IAAM,WAAW,eAAA,CAAgB;AAAA,EACtC,IAAA,EAAM,UAAA;AAAA,EACN,YAAA,EAAc,KAAA;AAAA,EACd,KAAA,EAAO;AAAA,IACL,OAAA,EAAS,EAAE,IAAA,EAAM,CAAC,QAAQ,MAAM,CAAA,EAAgC,SAAS,UAAA,EAAW;AAAA;AAAA,IAEpF,WAAA,EAAa,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAS,OAAA,EAAQ;AAAA;AAAA,IAE9C,MAAA,EAAQ,EAAE,IAAA,EAAM,CAAC,QAAQ,MAAM,CAAA,EAAG,SAAS,MAAA,EAAU;AAAA;AAAA,IAErD,SAAA,EAAW,EAAE,IAAA,EAAM,CAAC,QAAQ,MAAM,CAAA,EAAG,SAAS,MAAA,EAAU;AAAA;AAAA,IAExD,GAAA,EAAK,EAAE,IAAA,EAAM,CAAC,QAAQ,MAAM,CAAA,EAAG,SAAS,IAAA,EAAK;AAAA,IAC7C,MAAA,EAAQ,EAAE,IAAA,EAAM,OAAA,EAAS,SAAS,KAAA;AAAM,GAC1C;AAAA,EACA,KAAA,CAAM,KAAA,EAAO,EAAE,KAAA,EAAO,OAAM,EAAG;AAC7B,IAAA,MAAM,KAAA,GAAQ,SAAiC,MAAM;AACnD,MAAA,MAAM,WAAA,GAAc,cAAA,CAAe,KAAA,CAAM,OAAA,EAAS,MAAM,WAAW,CAAA;AACnE,MAAA,MAAM,MAAA,GACJ,KAAA,CAAM,MAAA,KAAW,MAAA,GAAY,YAAA,CAAa,MAAM,MAAM,CAAA,GAAI,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA;AAClF,MAAA,MAAM,MAAA,GACJ,KAAA,CAAM,SAAA,KAAc,MAAA,GAAY,YAAA,CAAa,MAAM,SAAS,CAAA,GAAI,YAAA,CAAa,KAAA,CAAM,GAAG,CAAA;AACxF,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA,CAAM,MAAA,GAAS,aAAA,GAAgB,MAAA;AAAA,QACxC,mBAAA,EAAqB,WAAA;AAAA,QACrB,MAAA;AAAA,QACA,SAAA,EAAW;AAAA,OACb;AAAA,IACF,CAAC,CAAA;AAED,IAAA,OAAO,MACL,CAAA;AAAA,MACE,KAAA;AAAA,MACA;AAAA,QACE,GAAG,KAAA;AAAA,QACH,gBAAA,EAAkB,EAAA;AAAA,QAClB,wBAAA,EAA0B,MAAA,CAAO,KAAA,CAAM,OAAO,CAAA;AAAA,QAC9C,KAAA,EAAO,EAAE,GAAG,KAAA,CAAM,OAAO,GAAK,KAAA,CAAM,KAAA,IAAgD,EAAC;AAAG,OAC1F;AAAA,MACA,MAAM,OAAA;AAAU,KAClB;AAAA,EACJ;AACF,CAAC","file":"chunk-WL67XCH5.js","sourcesContent":["import { computed, defineComponent, h, type PropType } from 'vue'\n\nexport type IrisGridColumns =\n | number\n | 'auto-fit'\n | 'auto-fill'\n | string /* raw grid-template-columns value */\n\nfunction resolveColumns(columns: IrisGridColumns, minColWidth: string): string {\n if (typeof columns === 'number') return `repeat(${columns}, minmax(0, 1fr))`\n if (columns === 'auto-fit') return `repeat(auto-fit, minmax(${minColWidth}, 1fr))`\n if (columns === 'auto-fill') return `repeat(auto-fill, minmax(${minColWidth}, 1fr))`\n return columns\n}\n\nfunction toCssSpacing(spacing: string | number): string {\n if (typeof spacing === 'number') return `${spacing}px`\n if (spacing === 'sm' || spacing === 'md' || spacing === 'lg') {\n return `var(--iris-gap-${spacing})`\n }\n return spacing\n}\n\n/**\n * Two-dimensional grid layout primitive. Three column modes:\n *\n * - **Fixed integer** — `columns={3}` → three equal-width columns.\n * - **Responsive auto-fit** — `columns=\"auto-fit\"` + `minColWidth` → fluid\n * grid where columns add/remove with container width. Most common.\n * - **Raw CSS** — pass any `grid-template-columns` string.\n *\n * Spacing accepts token shorthand (`sm` / `md` / `lg`), numeric px, or any\n * CSS length string. `gap` is a shortcut for both row + column gap.\n */\nexport const IrisGrid = defineComponent({\n name: 'IrisGrid',\n inheritAttrs: false,\n props: {\n columns: { type: [Number, String] as PropType<IrisGridColumns>, default: 'auto-fit' },\n /** Min width per column for `auto-fit` / `auto-fill`. */\n minColWidth: { type: String, default: '200px' },\n /** Row gap (token / px / CSS). */\n rowGap: { type: [String, Number], default: undefined },\n /** Column gap (token / px / CSS). */\n columnGap: { type: [String, Number], default: undefined },\n /** Shorthand for both row + column gap. Overridden if rowGap/columnGap given. */\n gap: { type: [String, Number], default: 'md' },\n inline: { type: Boolean, default: false },\n },\n setup(props, { slots, attrs }) {\n const style = computed<Record<string, string>>(() => {\n const colTemplate = resolveColumns(props.columns, props.minColWidth)\n const rowGap =\n props.rowGap !== undefined ? toCssSpacing(props.rowGap) : toCssSpacing(props.gap)\n const colGap =\n props.columnGap !== undefined ? toCssSpacing(props.columnGap) : toCssSpacing(props.gap)\n return {\n display: props.inline ? 'inline-grid' : 'grid',\n gridTemplateColumns: colTemplate,\n rowGap,\n columnGap: colGap,\n }\n })\n\n return () =>\n h(\n 'div',\n {\n ...attrs,\n 'data-iris-grid': '',\n 'data-iris-grid-columns': String(props.columns),\n style: { ...style.value, ...((attrs.style as Record<string, string> | undefined) ?? {}) },\n },\n slots.default?.(),\n )\n },\n})\n"]}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { watch, onScopeDispose } from 'vue';
|
|
2
|
+
|
|
3
|
+
// src/primitives/modal-utils/useFocusTrap.ts
|
|
4
|
+
var FOCUSABLE_SELECTOR = [
|
|
5
|
+
"a[href]",
|
|
6
|
+
"area[href]",
|
|
7
|
+
"button:not([disabled])",
|
|
8
|
+
'input:not([disabled]):not([type="hidden"])',
|
|
9
|
+
"select:not([disabled])",
|
|
10
|
+
"textarea:not([disabled])",
|
|
11
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
12
|
+
'[contenteditable="true"]',
|
|
13
|
+
"audio[controls]",
|
|
14
|
+
"video[controls]",
|
|
15
|
+
"iframe",
|
|
16
|
+
"object",
|
|
17
|
+
"embed"
|
|
18
|
+
].join(",");
|
|
19
|
+
function getFocusable(root) {
|
|
20
|
+
return Array.from(root.querySelectorAll(FOCUSABLE_SELECTOR)).filter(
|
|
21
|
+
(el) => !el.hasAttribute("disabled") && el.tabIndex !== -1
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function useFocusTrap(options) {
|
|
25
|
+
let previouslyFocused = null;
|
|
26
|
+
const onKeyDown = (event) => {
|
|
27
|
+
if (!options.active.value || event.key !== "Tab") return;
|
|
28
|
+
const root = options.container.value;
|
|
29
|
+
if (!root) return;
|
|
30
|
+
const focusables = getFocusable(root);
|
|
31
|
+
if (focusables.length === 0) {
|
|
32
|
+
event.preventDefault();
|
|
33
|
+
root.focus();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const first = focusables[0];
|
|
37
|
+
const last = focusables[focusables.length - 1];
|
|
38
|
+
const active = document.activeElement;
|
|
39
|
+
if (event.shiftKey) {
|
|
40
|
+
if (active === first || !root.contains(active)) {
|
|
41
|
+
event.preventDefault();
|
|
42
|
+
last.focus();
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
if (active === last || !root.contains(active)) {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
first.focus();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
const activate = () => {
|
|
52
|
+
if (typeof document === "undefined") return;
|
|
53
|
+
previouslyFocused = document.activeElement ?? null;
|
|
54
|
+
document.addEventListener("keydown", onKeyDown);
|
|
55
|
+
if (options.initialFocus !== false) {
|
|
56
|
+
requestAnimationFrame(() => {
|
|
57
|
+
const root = options.container.value;
|
|
58
|
+
if (!root) return;
|
|
59
|
+
const focusables = getFocusable(root);
|
|
60
|
+
(focusables[0] ?? root).focus();
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const deactivate = () => {
|
|
65
|
+
if (typeof document === "undefined") return;
|
|
66
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
67
|
+
const restore = options.returnFocusTo?.value ?? previouslyFocused;
|
|
68
|
+
requestAnimationFrame(() => {
|
|
69
|
+
if (restore && restore.isConnected) restore.focus?.();
|
|
70
|
+
});
|
|
71
|
+
previouslyFocused = null;
|
|
72
|
+
};
|
|
73
|
+
watch(
|
|
74
|
+
options.active,
|
|
75
|
+
(active, wasActive) => {
|
|
76
|
+
if (active && !wasActive) activate();
|
|
77
|
+
else if (!active && wasActive) deactivate();
|
|
78
|
+
},
|
|
79
|
+
{ immediate: true, flush: "post" }
|
|
80
|
+
);
|
|
81
|
+
onScopeDispose(() => {
|
|
82
|
+
if (typeof document !== "undefined") {
|
|
83
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
var lockCount = 0;
|
|
88
|
+
var savedOverflow = null;
|
|
89
|
+
var savedPaddingRight = null;
|
|
90
|
+
var appliedOverflow = null;
|
|
91
|
+
var appliedPaddingRight = null;
|
|
92
|
+
function lock() {
|
|
93
|
+
if (typeof document === "undefined") return;
|
|
94
|
+
lockCount += 1;
|
|
95
|
+
if (lockCount > 1) return;
|
|
96
|
+
const body = document.body;
|
|
97
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
98
|
+
savedOverflow = body.style.overflow;
|
|
99
|
+
savedPaddingRight = body.style.paddingRight;
|
|
100
|
+
body.style.overflow = "hidden";
|
|
101
|
+
appliedOverflow = "hidden";
|
|
102
|
+
if (scrollbarWidth > 0) {
|
|
103
|
+
const currentPadding = parseFloat(getComputedStyle(body).paddingRight || "0");
|
|
104
|
+
appliedPaddingRight = `${currentPadding + scrollbarWidth}px`;
|
|
105
|
+
body.style.paddingRight = appliedPaddingRight;
|
|
106
|
+
} else {
|
|
107
|
+
appliedPaddingRight = null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function unlock() {
|
|
111
|
+
if (typeof document === "undefined") return;
|
|
112
|
+
lockCount = Math.max(0, lockCount - 1);
|
|
113
|
+
if (lockCount > 0) return;
|
|
114
|
+
const body = document.body;
|
|
115
|
+
if (body.style.overflow === appliedOverflow) {
|
|
116
|
+
body.style.overflow = savedOverflow ?? "";
|
|
117
|
+
}
|
|
118
|
+
if (appliedPaddingRight !== null && body.style.paddingRight === appliedPaddingRight) {
|
|
119
|
+
body.style.paddingRight = savedPaddingRight ?? "";
|
|
120
|
+
}
|
|
121
|
+
savedOverflow = null;
|
|
122
|
+
savedPaddingRight = null;
|
|
123
|
+
appliedOverflow = null;
|
|
124
|
+
appliedPaddingRight = null;
|
|
125
|
+
}
|
|
126
|
+
function useBodyScrollLock(active) {
|
|
127
|
+
let isLockedByThis = false;
|
|
128
|
+
watch(
|
|
129
|
+
active,
|
|
130
|
+
(value) => {
|
|
131
|
+
if (value && !isLockedByThis) {
|
|
132
|
+
lock();
|
|
133
|
+
isLockedByThis = true;
|
|
134
|
+
} else if (!value && isLockedByThis) {
|
|
135
|
+
unlock();
|
|
136
|
+
isLockedByThis = false;
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
{ immediate: true, flush: "post" }
|
|
140
|
+
);
|
|
141
|
+
onScopeDispose(() => {
|
|
142
|
+
if (isLockedByThis) {
|
|
143
|
+
unlock();
|
|
144
|
+
isLockedByThis = false;
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function __getBodyScrollLockCount() {
|
|
149
|
+
return lockCount;
|
|
150
|
+
}
|
|
151
|
+
function __resetBodyScrollLock() {
|
|
152
|
+
lockCount = 0;
|
|
153
|
+
savedOverflow = null;
|
|
154
|
+
savedPaddingRight = null;
|
|
155
|
+
appliedOverflow = null;
|
|
156
|
+
appliedPaddingRight = null;
|
|
157
|
+
if (typeof document !== "undefined") {
|
|
158
|
+
document.body.style.overflow = "";
|
|
159
|
+
document.body.style.paddingRight = "";
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export { __getBodyScrollLockCount, __resetBodyScrollLock, useBodyScrollLock, useFocusTrap };
|
|
164
|
+
//# sourceMappingURL=chunk-XCNCIG2I.js.map
|
|
165
|
+
//# sourceMappingURL=chunk-XCNCIG2I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/primitives/modal-utils/useFocusTrap.ts","../src/primitives/modal-utils/useBodyScrollLock.ts"],"names":["watch","onScopeDispose"],"mappings":"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","file":"chunk-XCNCIG2I.js","sourcesContent":["import { onScopeDispose, watch, type Ref } from 'vue'\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled]):not([type=\"hidden\"])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n '[contenteditable=\"true\"]',\n 'audio[controls]',\n 'video[controls]',\n 'iframe',\n 'object',\n 'embed',\n].join(',')\n\nfunction getFocusable(root: HTMLElement): HTMLElement[] {\n return Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (el) => !el.hasAttribute('disabled') && el.tabIndex !== -1,\n )\n}\n\nexport interface UseFocusTrapOptions {\n /** Element whose Tab key cycle is being trapped. */\n container: Ref<HTMLElement | null>\n /** Whether the trap is currently active. */\n active: Ref<boolean>\n /** Element to restore focus to when the trap deactivates. */\n returnFocusTo?: Ref<HTMLElement | null | undefined>\n /** Whether to focus the first focusable element on activation. Default `true`. */\n initialFocus?: boolean\n}\n\n/**\n * Constrain Tab / Shift+Tab focus traversal to descendants of `container`.\n *\n * Behavior on activation:\n * - Records the currently focused element.\n * - If `initialFocus !== false`, focuses the first focusable descendant\n * (or the container itself if there are none).\n *\n * Behavior while active:\n * - Tab on the last focusable element wraps to the first; Shift+Tab on\n * the first wraps to the last.\n *\n * Behavior on deactivation:\n * - Restores focus to `returnFocusTo?.value` if provided, else to the\n * element that was focused when the trap activated.\n */\nexport function useFocusTrap(options: UseFocusTrapOptions): void {\n let previouslyFocused: HTMLElement | null = null\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (!options.active.value || event.key !== 'Tab') return\n const root = options.container.value\n if (!root) return\n const focusables = getFocusable(root)\n if (focusables.length === 0) {\n event.preventDefault()\n root.focus()\n return\n }\n const first = focusables[0]!\n const last = focusables[focusables.length - 1]!\n const active = document.activeElement as HTMLElement | null\n\n if (event.shiftKey) {\n if (active === first || !root.contains(active)) {\n event.preventDefault()\n last.focus()\n }\n } else {\n if (active === last || !root.contains(active)) {\n event.preventDefault()\n first.focus()\n }\n }\n }\n\n const activate = () => {\n if (typeof document === 'undefined') return\n previouslyFocused = (document.activeElement as HTMLElement | null) ?? null\n document.addEventListener('keydown', onKeyDown)\n if (options.initialFocus !== false) {\n requestAnimationFrame(() => {\n const root = options.container.value\n if (!root) return\n const focusables = getFocusable(root)\n ;(focusables[0] ?? root).focus()\n })\n }\n }\n\n const deactivate = () => {\n if (typeof document === 'undefined') return\n document.removeEventListener('keydown', onKeyDown)\n const restore = options.returnFocusTo?.value ?? previouslyFocused\n requestAnimationFrame(() => {\n // The element that had focus when the trap opened may have been\n // unmounted while it was open; focusing a detached node silently drops\n // focus to <body>. Only restore if it is still in the document.\n if (restore && restore.isConnected) restore.focus?.()\n })\n previouslyFocused = null\n }\n\n watch(\n options.active,\n (active, wasActive) => {\n if (active && !wasActive) activate()\n else if (!active && wasActive) deactivate()\n },\n { immediate: true, flush: 'post' },\n )\n\n onScopeDispose(() => {\n if (typeof document !== 'undefined') {\n document.removeEventListener('keydown', onKeyDown)\n }\n })\n}\n","import { onScopeDispose, watch, type Ref } from 'vue'\n\nlet lockCount = 0\nlet savedOverflow: string | null = null\nlet savedPaddingRight: string | null = null\n// What we actually wrote, so unlock can detect a host mutation made while\n// locked and avoid clobbering it.\nlet appliedOverflow: string | null = null\nlet appliedPaddingRight: string | null = null\n\nfunction lock() {\n if (typeof document === 'undefined') return\n lockCount += 1\n if (lockCount > 1) return\n const body = document.body\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth\n savedOverflow = body.style.overflow\n savedPaddingRight = body.style.paddingRight\n body.style.overflow = 'hidden'\n appliedOverflow = 'hidden'\n if (scrollbarWidth > 0) {\n const currentPadding = parseFloat(getComputedStyle(body).paddingRight || '0')\n appliedPaddingRight = `${currentPadding + scrollbarWidth}px`\n body.style.paddingRight = appliedPaddingRight\n } else {\n appliedPaddingRight = null\n }\n}\n\nfunction unlock() {\n if (typeof document === 'undefined') return\n lockCount = Math.max(0, lockCount - 1)\n if (lockCount > 0) return\n const body = document.body\n // Only restore if our locked value is still in place; if a host changed body\n // overflow / padding-right while locked, respect that rather than clobber it.\n if (body.style.overflow === appliedOverflow) {\n body.style.overflow = savedOverflow ?? ''\n }\n if (appliedPaddingRight !== null && body.style.paddingRight === appliedPaddingRight) {\n body.style.paddingRight = savedPaddingRight ?? ''\n }\n savedOverflow = null\n savedPaddingRight = null\n appliedOverflow = null\n appliedPaddingRight = null\n}\n\n/**\n * Lock the document body's scroll while `active` is true. Reference-counted\n * so multiple stacked Dialogs cooperate. Restores prior `overflow` and\n * `padding-right` (to compensate for the scrollbar gap) when the last lock\n * releases. SSR-safe.\n */\nexport function useBodyScrollLock(active: Ref<boolean>): void {\n let isLockedByThis = false\n\n watch(\n active,\n (value) => {\n if (value && !isLockedByThis) {\n lock()\n isLockedByThis = true\n } else if (!value && isLockedByThis) {\n unlock()\n isLockedByThis = false\n }\n },\n { immediate: true, flush: 'post' },\n )\n\n onScopeDispose(() => {\n if (isLockedByThis) {\n unlock()\n isLockedByThis = false\n }\n })\n}\n\n/** Test-only: read the current lock count. */\nexport function __getBodyScrollLockCount(): number {\n return lockCount\n}\n\n/** Test-only: hard-reset the module-level lock state. */\nexport function __resetBodyScrollLock(): void {\n lockCount = 0\n savedOverflow = null\n savedPaddingRight = null\n appliedOverflow = null\n appliedPaddingRight = null\n if (typeof document !== 'undefined') {\n document.body.style.overflow = ''\n document.body.style.paddingRight = ''\n }\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { shallowRef, onBeforeUnmount } from 'vue';
|
|
2
|
+
import { createResourceController } from '@iris-ui-kit/core';
|
|
3
|
+
export { createClientFetcher, createResourceController } from '@iris-ui-kit/core';
|
|
4
|
+
|
|
5
|
+
// src/resource/useResourceController.ts
|
|
6
|
+
function useResourceController(config) {
|
|
7
|
+
const controller = createResourceController(config);
|
|
8
|
+
const state = shallowRef(controller.getState());
|
|
9
|
+
onBeforeUnmount(controller.subscribe((next) => state.value = next));
|
|
10
|
+
onBeforeUnmount(() => controller.destroy());
|
|
11
|
+
return { ...controller, state };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { useResourceController };
|
|
15
|
+
//# sourceMappingURL=chunk-XSLBANUV.js.map
|
|
16
|
+
//# sourceMappingURL=chunk-XSLBANUV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resource/useResourceController.ts"],"names":[],"mappings":";;;;;AAmBO,SAAS,sBACd,MAAA,EAC0B;AAC1B,EAAA,MAAM,UAAA,GAAa,yBAAyB,MAAM,CAAA;AAClD,EAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,UAAA,CAAW,QAAA,EAAU,CAAA;AAC9C,EAAA,eAAA,CAAgB,WAAW,SAAA,CAAU,CAAC,SAAU,KAAA,CAAM,KAAA,GAAQ,IAAK,CAAC,CAAA;AAGpE,EAAA,eAAA,CAAgB,MAAM,UAAA,CAAW,OAAA,EAAS,CAAA;AAC1C,EAAA,OAAO,EAAE,GAAG,UAAA,EAAY,KAAA,EAAM;AAChC","file":"chunk-XSLBANUV.js","sourcesContent":["import { onBeforeUnmount, shallowRef, type ShallowRef } from 'vue'\nimport {\n createResourceController,\n type ResourceController,\n type ResourceControllerConfig,\n type ResourceState,\n} from '@iris-ui-kit/core'\n\nexport interface UseResourceController<T> extends ResourceController<T> {\n /** The live resource state as a reactive ref (rows, total, page, loading, selectedKeys). */\n state: ShallowRef<ResourceState<T>>\n}\n\n/**\n * Vue bridge over the framework-agnostic {@link createResourceController} (L4\n * CRUD list composite). Creates the controller once in `setup()`, mirrors its\n * store into a `shallowRef`, and returns the controller plus that live `state`.\n * A ~15-line thin bridge — all logic lives in `@iris-ui-kit/core`.\n */\nexport function useResourceController<T>(\n config: ResourceControllerConfig<T>,\n): UseResourceController<T> {\n const controller = createResourceController(config)\n const state = shallowRef(controller.getState())\n onBeforeUnmount(controller.subscribe((next) => (state.value = next)))\n // Abort any in-flight fetch + detach the controller's internal subscriptions\n // on unmount (a late response must not write back to a torn-down instance).\n onBeforeUnmount(() => controller.destroy())\n return { ...controller, state }\n}\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { ref, onBeforeUnmount, onMounted, computed } from 'vue';
|
|
2
|
+
import { createAsyncResource, createPaginatedResource } from '@iris-ui-kit/core';
|
|
3
|
+
|
|
4
|
+
// src/async/useAsyncResource.ts
|
|
5
|
+
function useAsyncResource(fetcher, options = {}) {
|
|
6
|
+
const config = "initialData" in options ? { initialData: options.initialData } : {};
|
|
7
|
+
const resource = createAsyncResource(fetcher, config);
|
|
8
|
+
const state = ref(resource.getState());
|
|
9
|
+
const unsubscribe = resource.subscribe((next) => {
|
|
10
|
+
state.value = next;
|
|
11
|
+
});
|
|
12
|
+
onBeforeUnmount(() => {
|
|
13
|
+
unsubscribe();
|
|
14
|
+
resource.cancel();
|
|
15
|
+
});
|
|
16
|
+
if (options.immediate) {
|
|
17
|
+
onMounted(() => {
|
|
18
|
+
void resource.load(...[]);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
status: computed(() => state.value.status),
|
|
23
|
+
data: computed(() => state.value.data),
|
|
24
|
+
error: computed(() => state.value.error),
|
|
25
|
+
isLoading: computed(() => state.value.status === "loading"),
|
|
26
|
+
isError: computed(() => state.value.status === "error"),
|
|
27
|
+
load: resource.load,
|
|
28
|
+
reload: resource.reload,
|
|
29
|
+
mutate: resource.mutate,
|
|
30
|
+
cancel: resource.cancel,
|
|
31
|
+
reset: resource.reset
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function usePaginatedResource(fetcher, options = {}) {
|
|
35
|
+
const resource = createPaginatedResource(fetcher, {
|
|
36
|
+
pageSize: options.pageSize,
|
|
37
|
+
mode: options.mode
|
|
38
|
+
});
|
|
39
|
+
const state = ref(resource.getState());
|
|
40
|
+
const unsubscribe = resource.subscribe((next) => {
|
|
41
|
+
state.value = next;
|
|
42
|
+
});
|
|
43
|
+
onBeforeUnmount(unsubscribe);
|
|
44
|
+
if (options.immediate) {
|
|
45
|
+
onMounted(() => {
|
|
46
|
+
void (options.mode === "infinite" ? resource.loadMore() : resource.goToPage(1));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
status: computed(() => state.value.status),
|
|
51
|
+
items: computed(() => state.value.items),
|
|
52
|
+
page: computed(() => state.value.page),
|
|
53
|
+
pageSize: computed(() => state.value.pageSize),
|
|
54
|
+
total: computed(() => state.value.total),
|
|
55
|
+
error: computed(() => state.value.error),
|
|
56
|
+
isLoading: computed(() => state.value.status === "loading"),
|
|
57
|
+
isError: computed(() => state.value.status === "error"),
|
|
58
|
+
// Touch state so this recomputes on every store change; hasMore() then
|
|
59
|
+
// reads the resource's fresh internal batch state.
|
|
60
|
+
hasMore: computed(() => {
|
|
61
|
+
void state.value;
|
|
62
|
+
return resource.hasMore();
|
|
63
|
+
}),
|
|
64
|
+
goToPage: resource.goToPage,
|
|
65
|
+
loadMore: resource.loadMore,
|
|
66
|
+
refresh: resource.refresh,
|
|
67
|
+
setPageSize: resource.setPageSize
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { useAsyncResource, usePaginatedResource };
|
|
72
|
+
//# sourceMappingURL=chunk-ZY4NLITM.js.map
|
|
73
|
+
//# sourceMappingURL=chunk-ZY4NLITM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/async/useAsyncResource.ts","../src/async/usePaginatedResource.ts"],"names":["ref","onBeforeUnmount","onMounted","computed"],"mappings":"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","file":"chunk-ZY4NLITM.js","sourcesContent":["import { computed, onBeforeUnmount, onMounted, ref, type ComputedRef, type Ref } from 'vue'\nimport {\n createAsyncResource,\n type AsyncResource,\n type AsyncResourceConfig,\n type AsyncState,\n type AsyncStatus,\n} from '@iris-ui-kit/core'\n\nexport interface UseAsyncResourceOptions<T> extends AsyncResourceConfig<T> {\n /** Run `load()` (no params) once on mount. Default `false`. */\n immediate?: boolean\n}\n\nexport interface UseAsyncResourceReturn<T, P extends unknown[]> {\n status: ComputedRef<AsyncStatus>\n data: ComputedRef<T | undefined>\n error: ComputedRef<unknown>\n isLoading: ComputedRef<boolean>\n isError: ComputedRef<boolean>\n load: AsyncResource<T, P>['load']\n reload: AsyncResource<T, P>['reload']\n mutate: AsyncResource<T, P>['mutate']\n cancel: AsyncResource<T, P>['cancel']\n reset: AsyncResource<T, P>['reset']\n}\n\n/**\n * Vue binding for the framework-agnostic async resource. Creates the resource\n * in `setup()` (runs once, so the fetcher closure stays live) and bridges its\n * state into computed refs.\n *\n * ```ts\n * const users = useAsyncResource(() => api.listUsers(), { immediate: true })\n * // <IrisTable :data=\"users.data.value ?? []\" :loading=\"users.isLoading.value\" />\n * ```\n */\nexport function useAsyncResource<T, P extends unknown[] = []>(\n fetcher: (...params: P) => Promise<T>,\n options: UseAsyncResourceOptions<T> = {},\n): UseAsyncResourceReturn<T, P> {\n const config: AsyncResourceConfig<T> =\n 'initialData' in options ? { initialData: options.initialData } : {}\n const resource = createAsyncResource<T, P>(fetcher, config)\n\n const state = ref(resource.getState()) as Ref<AsyncState<T>>\n const unsubscribe = resource.subscribe((next) => {\n state.value = next\n })\n onBeforeUnmount(() => {\n unsubscribe()\n // Abort any in-flight request on unmount so it can't write back into an\n // unmounted component (and cancels the underlying request when the fetcher\n // honors `signal`). Idempotent and safe with no in-flight load.\n resource.cancel()\n })\n\n if (options.immediate) {\n onMounted(() => {\n void resource.load(...([] as unknown as P))\n })\n }\n\n return {\n status: computed(() => state.value.status),\n data: computed(() => state.value.data),\n error: computed(() => state.value.error),\n isLoading: computed(() => state.value.status === 'loading'),\n isError: computed(() => state.value.status === 'error'),\n load: resource.load,\n reload: resource.reload,\n mutate: resource.mutate,\n cancel: resource.cancel,\n reset: resource.reset,\n }\n}\n","import { computed, onBeforeUnmount, onMounted, ref, type ComputedRef, type Ref } from 'vue'\nimport {\n createPaginatedResource,\n type PageQuery,\n type PageResult,\n type PaginatedResource,\n type PaginatedState,\n type PaginationMode,\n} from '@iris-ui-kit/core'\n\nexport interface UsePaginatedResourceOptions {\n pageSize?: number\n mode?: PaginationMode\n /** Load the first page on mount (page 1, or `loadMore` in infinite mode). */\n immediate?: boolean\n}\n\nexport interface UsePaginatedResourceReturn<T> {\n status: ComputedRef<PaginatedState<T>['status']>\n items: ComputedRef<T[]>\n page: ComputedRef<number>\n pageSize: ComputedRef<number>\n total: ComputedRef<number | undefined>\n error: ComputedRef<unknown>\n isLoading: ComputedRef<boolean>\n isError: ComputedRef<boolean>\n hasMore: ComputedRef<boolean>\n goToPage: PaginatedResource<T>['goToPage']\n loadMore: PaginatedResource<T>['loadMore']\n refresh: PaginatedResource<T>['refresh']\n setPageSize: PaginatedResource<T>['setPageSize']\n}\n\n/**\n * Vue binding for the server-side pagination resource. Created in `setup()`\n * (fetcher closure stays live) and bridged to computed refs.\n */\nexport function usePaginatedResource<T>(\n fetcher: (query: PageQuery) => Promise<PageResult<T>>,\n options: UsePaginatedResourceOptions = {},\n): UsePaginatedResourceReturn<T> {\n const resource = createPaginatedResource<T>(fetcher, {\n pageSize: options.pageSize,\n mode: options.mode,\n })\n\n const state = ref(resource.getState()) as Ref<PaginatedState<T>>\n const unsubscribe = resource.subscribe((next) => {\n state.value = next\n })\n onBeforeUnmount(unsubscribe)\n\n if (options.immediate) {\n onMounted(() => {\n void (options.mode === 'infinite' ? resource.loadMore() : resource.goToPage(1))\n })\n }\n\n return {\n status: computed(() => state.value.status),\n items: computed(() => state.value.items),\n page: computed(() => state.value.page),\n pageSize: computed(() => state.value.pageSize),\n total: computed(() => state.value.total),\n error: computed(() => state.value.error),\n isLoading: computed(() => state.value.status === 'loading'),\n isError: computed(() => state.value.status === 'error'),\n // Touch state so this recomputes on every store change; hasMore() then\n // reads the resource's fresh internal batch state.\n hasMore: computed(() => {\n void state.value\n return resource.hasMore()\n }),\n goToPage: resource.goToPage,\n loadMore: resource.loadMore,\n refresh: resource.refresh,\n setPageSize: resource.setPageSize,\n }\n}\n"]}
|
package/dist/data.cjs
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var vue = require('vue');
|
|
4
|
+
var core = require('@iris-ui-kit/core');
|
|
5
|
+
|
|
6
|
+
// src/data/useDataSource.ts
|
|
7
|
+
function useStore(store) {
|
|
8
|
+
const state = vue.shallowRef(store.getState());
|
|
9
|
+
vue.onScopeDispose(store.subscribe((next) => state.value = next));
|
|
10
|
+
return state;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// src/data/useDataSource.ts
|
|
14
|
+
function useDataSource(config) {
|
|
15
|
+
const controller = core.createDataSource({ ...config, immediate: false });
|
|
16
|
+
const immediate = config.immediate !== false;
|
|
17
|
+
vue.onMounted(() => {
|
|
18
|
+
if (immediate) void controller.load();
|
|
19
|
+
});
|
|
20
|
+
vue.onScopeDispose(() => controller.destroy());
|
|
21
|
+
const state = useStore(controller.store);
|
|
22
|
+
return { ...controller, state };
|
|
23
|
+
}
|
|
24
|
+
function useGroupedView(config) {
|
|
25
|
+
const controller = core.createGroupedView(config);
|
|
26
|
+
const storeRef = useStore(controller.store);
|
|
27
|
+
const state = vue.computed(() => {
|
|
28
|
+
const s = storeRef.value;
|
|
29
|
+
return s.state;
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
store: controller.store,
|
|
33
|
+
setRows: (rows, columns) => controller.setRows(rows, columns),
|
|
34
|
+
toggleGroup: (key) => controller.toggleGroup(key),
|
|
35
|
+
expandGroup: (key) => controller.expandGroup(key),
|
|
36
|
+
collapseGroup: (key) => controller.collapseGroup(key),
|
|
37
|
+
expandAll: () => controller.expandAll(),
|
|
38
|
+
collapseAll: () => controller.collapseAll(),
|
|
39
|
+
state,
|
|
40
|
+
setConfig: (partial) => controller.setConfig(partial)
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Object.defineProperty(exports, "createClientDataSource", {
|
|
45
|
+
enumerable: true,
|
|
46
|
+
get: function () { return core.createClientDataSource; }
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "createDataSource", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return core.createDataSource; }
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(exports, "createGroupedView", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () { return core.createGroupedView; }
|
|
55
|
+
});
|
|
56
|
+
exports.useDataSource = useDataSource;
|
|
57
|
+
exports.useGroupedView = useGroupedView;
|
|
58
|
+
//# sourceMappingURL=data.cjs.map
|
|
59
|
+
//# sourceMappingURL=data.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/useStore.ts","../src/data/useDataSource.ts","../src/data/useGroupedView.ts"],"names":["shallowRef","onScopeDispose","createDataSource","onMounted","createGroupedView","computed"],"mappings":";;;;;;AASO,SAAS,SAAY,KAAA,EAAkD;AAC5E,EAAA,MAAM,KAAA,GAAQA,cAAA,CAAW,KAAA,CAAM,QAAA,EAAU,CAAA;AACzC,EAAAC,kBAAA,CAAe,MAAM,SAAA,CAAU,CAAC,SAAU,KAAA,CAAM,KAAA,GAAQ,IAAK,CAAC,CAAA;AAC9D,EAAA,OAAO,KAAA;AACT;;;ACiBO,SAAS,cAAiB,MAAA,EAA+C;AAC9E,EAAA,MAAM,aAAaC,qBAAA,CAAiB,EAAE,GAAG,MAAA,EAAQ,SAAA,EAAW,OAAO,CAAA;AACnE,EAAA,MAAM,SAAA,GAAY,OAAO,SAAA,KAAc,KAAA;AAEvC,EAAAC,aAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAA,EAAW,KAAK,UAAA,CAAW,IAAA,EAAK;AAAA,EACtC,CAAC,CAAA;AAGD,EAAAF,kBAAAA,CAAe,MAAM,UAAA,CAAW,OAAA,EAAS,CAAA;AAEzC,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AACvC,EAAA,OAAO,EAAE,GAAG,UAAA,EAAY,KAAA,EAAM;AAChC;ACfO,SAAS,eACd,MAAA,EACwB;AACxB,EAAA,MAAM,UAAA,GAAaG,uBAA0B,MAAM,CAAA;AACnD,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,UAAA,CAAW,KAAK,CAAA;AAC1C,EAAA,MAAM,KAAA,GAAQC,aAAS,MAAM;AAC3B,IAAA,MAAM,IAAI,QAAA,CAAS,KAAA;AACnB,IAAA,OAAO,CAAA,CAAE,KAAA;AAAA,EACX,CAAC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,OAAO,UAAA,CAAW,KAAA;AAAA,IAClB,SAAS,CAAC,IAAA,EAAM,YAAY,UAAA,CAAW,OAAA,CAAQ,MAAM,OAAO,CAAA;AAAA,IAC5D,WAAA,EAAa,CAAC,GAAA,KAAQ,UAAA,CAAW,YAAY,GAAG,CAAA;AAAA,IAChD,WAAA,EAAa,CAAC,GAAA,KAAQ,UAAA,CAAW,YAAY,GAAG,CAAA;AAAA,IAChD,aAAA,EAAe,CAAC,GAAA,KAAQ,UAAA,CAAW,cAAc,GAAG,CAAA;AAAA,IACpD,SAAA,EAAW,MAAM,UAAA,CAAW,SAAA,EAAU;AAAA,IACtC,WAAA,EAAa,MAAM,UAAA,CAAW,WAAA,EAAY;AAAA,IAC1C,KAAA;AAAA,IACA,SAAA,EAAW,CAAC,OAAA,KAAY,UAAA,CAAW,UAAU,OAAO;AAAA,GACtD;AACF","file":"data.cjs","sourcesContent":["import { shallowRef, onScopeDispose, type ShallowRef } from 'vue'\nimport type { ReadonlyStore, Store } from '@iris-ui-kit/core'\n\n/**\n * Bridge a framework-agnostic `@iris-ui-kit/core` store into a Vue ref — updates on\n * every store emission. The mirror of React's `useSyncExternalStore`, Solid's\n * `createSignal`, and Svelte's `readable`. Seeds synchronously from\n * `store.getState()` (SSR-safe); detaches on scope dispose.\n */\nexport function useStore<T>(store: ReadonlyStore<T>): Readonly<ShallowRef<T>> {\n const state = shallowRef(store.getState()) as ShallowRef<T>\n onScopeDispose(store.subscribe((next) => (state.value = next)))\n return state\n}\n\n/**\n * Subscribe to a DERIVED slice of a core store — the ref updates only when\n * `selector(state)` changes per `equals` (default `Object.is`), not on every\n * store emission. Built on {@link Store.subscribeWith}.\n */\nexport function useStoreSelector<T, U>(\n store: Store<T>,\n selector: (state: T) => U,\n equals?: (a: U, b: U) => boolean,\n): Readonly<ShallowRef<U>> {\n const slice = shallowRef(selector(store.getState())) as ShallowRef<U>\n onScopeDispose(store.subscribeWith(selector, (v) => (slice.value = v), equals))\n return slice\n}\n","import { onMounted, onScopeDispose, type ShallowRef } from 'vue'\nimport {\n createDataSource,\n type DataSourceController,\n type DataSourceConfig,\n type DataSourceState,\n} from '@iris-ui-kit/core'\nimport { useStore } from '../useStore'\n\nexport interface UseDataSource<T> extends DataSourceController<T> {\n /**\n * The live data-source state as a reactive ref: rows, total, page/pageSize,\n * sort/multiSort, filters/filterRules, loading/loadingMore, hasMore,\n * selectedKeys, and the per-row pendingRows/rowErrors.\n */\n state: ShallowRef<DataSourceState<T>>\n}\n\n/**\n * Vue bridge over the framework-agnostic {@link createDataSource} — the unified\n * data engine (paged/infinite + multi-sort + typed filters + selection +\n * per-row + optimistic mutate). Creates the controller once in `setup()`,\n * mirrors its store into a reactive ref, and returns the controller plus its\n * live `state`. A thin bridge — all logic lives in `@iris-ui-kit/core`.\n *\n * Constructed with `immediate: false` so no fetch fires during `setup()`; the\n * initial load is kicked from `onMounted` and the controller is torn down on\n * scope dispose (aborting any in-flight request) so a late response never\n * writes back to a torn-down instance.\n */\nexport function useDataSource<T>(config: DataSourceConfig<T>): UseDataSource<T> {\n const controller = createDataSource({ ...config, immediate: false })\n const immediate = config.immediate !== false\n\n onMounted(() => {\n if (immediate) void controller.load()\n })\n // Abort any in-flight fetch + detach the controller's internal subscriptions\n // on unmount (a late response must not write back to a torn-down instance).\n onScopeDispose(() => controller.destroy())\n\n const state = useStore(controller.store)\n return { ...controller, state }\n}\n","import { computed, type ComputedRef } from 'vue'\nimport {\n createGroupedView,\n type GroupedViewConfig,\n type GroupedViewState,\n type GroupedViewStore,\n} from '@iris-ui-kit/core'\nimport type { DataViewColumn } from '@iris-ui-kit/core'\nimport { useStore } from '../useStore'\n\nexport interface UseGroupedView<Row, K = string> {\n store: ReturnType<typeof createGroupedView<Row, K>>['store']\n setRows: (rows: readonly Row[], columns?: readonly DataViewColumn<Row>[]) => void\n toggleGroup: (key: K) => void\n expandGroup: (key: K) => void\n collapseGroup: (key: K) => void\n expandAll: () => void\n collapseAll: () => void\n /** Reactive live grouped-view state. */\n state: ComputedRef<GroupedViewState<Row, K>>\n setConfig: (partial: Partial<GroupedViewConfig<Row, K>>) => void\n}\n\n/**\n * Vue bridge over the framework-agnostic {@link createGroupedView}.\n * Creates the controller once, subscribes its store to a reactive ref,\n * and returns the controller plus a computed `state`.\n */\nexport function useGroupedView<Row, K = string>(\n config: GroupedViewConfig<Row, K>,\n): UseGroupedView<Row, K> {\n const controller = createGroupedView<Row, K>(config)\n const storeRef = useStore(controller.store)\n const state = computed(() => {\n const s = storeRef.value as GroupedViewStore<Row, K>\n return s.state\n })\n\n return {\n store: controller.store,\n setRows: (rows, columns) => controller.setRows(rows, columns),\n toggleGroup: (key) => controller.toggleGroup(key),\n expandGroup: (key) => controller.expandGroup(key),\n collapseGroup: (key) => controller.collapseGroup(key),\n expandAll: () => controller.expandAll(),\n collapseAll: () => controller.collapseAll(),\n state,\n setConfig: (partial) => controller.setConfig(partial),\n }\n}\n"]}
|
package/dist/data.d.cts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ShallowRef, ComputedRef } from 'vue';
|
|
2
|
+
import { DataSourceController, DataSourceState, DataSourceConfig, createGroupedView, DataViewColumn, GroupedViewState, GroupedViewConfig } from '@iris-ui-kit/core';
|
|
3
|
+
export { DataSourceConfig, DataSourceController, DataSourceMode, DataSourceMutateOptions, DataSourceQuery, DataSourceState, GroupedViewConfig, GroupedViewState, GroupedViewStore, RowMutateOptions, createClientDataSource, createDataSource, createGroupedView } from '@iris-ui-kit/core';
|
|
4
|
+
|
|
5
|
+
interface UseDataSource<T> extends DataSourceController<T> {
|
|
6
|
+
/**
|
|
7
|
+
* The live data-source state as a reactive ref: rows, total, page/pageSize,
|
|
8
|
+
* sort/multiSort, filters/filterRules, loading/loadingMore, hasMore,
|
|
9
|
+
* selectedKeys, and the per-row pendingRows/rowErrors.
|
|
10
|
+
*/
|
|
11
|
+
state: ShallowRef<DataSourceState<T>>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Vue bridge over the framework-agnostic {@link createDataSource} — the unified
|
|
15
|
+
* data engine (paged/infinite + multi-sort + typed filters + selection +
|
|
16
|
+
* per-row + optimistic mutate). Creates the controller once in `setup()`,
|
|
17
|
+
* mirrors its store into a reactive ref, and returns the controller plus its
|
|
18
|
+
* live `state`. A thin bridge — all logic lives in `@iris-ui-kit/core`.
|
|
19
|
+
*
|
|
20
|
+
* Constructed with `immediate: false` so no fetch fires during `setup()`; the
|
|
21
|
+
* initial load is kicked from `onMounted` and the controller is torn down on
|
|
22
|
+
* scope dispose (aborting any in-flight request) so a late response never
|
|
23
|
+
* writes back to a torn-down instance.
|
|
24
|
+
*/
|
|
25
|
+
declare function useDataSource<T>(config: DataSourceConfig<T>): UseDataSource<T>;
|
|
26
|
+
|
|
27
|
+
interface UseGroupedView<Row, K = string> {
|
|
28
|
+
store: ReturnType<typeof createGroupedView<Row, K>>['store'];
|
|
29
|
+
setRows: (rows: readonly Row[], columns?: readonly DataViewColumn<Row>[]) => void;
|
|
30
|
+
toggleGroup: (key: K) => void;
|
|
31
|
+
expandGroup: (key: K) => void;
|
|
32
|
+
collapseGroup: (key: K) => void;
|
|
33
|
+
expandAll: () => void;
|
|
34
|
+
collapseAll: () => void;
|
|
35
|
+
/** Reactive live grouped-view state. */
|
|
36
|
+
state: ComputedRef<GroupedViewState<Row, K>>;
|
|
37
|
+
setConfig: (partial: Partial<GroupedViewConfig<Row, K>>) => void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Vue bridge over the framework-agnostic {@link createGroupedView}.
|
|
41
|
+
* Creates the controller once, subscribes its store to a reactive ref,
|
|
42
|
+
* and returns the controller plus a computed `state`.
|
|
43
|
+
*/
|
|
44
|
+
declare function useGroupedView<Row, K = string>(config: GroupedViewConfig<Row, K>): UseGroupedView<Row, K>;
|
|
45
|
+
|
|
46
|
+
export { type UseDataSource, type UseGroupedView, useDataSource, useGroupedView };
|