@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,1304 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ var React9 = require('react');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var core = require('@iris-ui-kit/core');
7
+
8
+ function _interopNamespace(e) {
9
+ if (e && e.__esModule) return e;
10
+ var n = Object.create(null);
11
+ if (e) {
12
+ Object.keys(e).forEach(function (k) {
13
+ if (k !== 'default') {
14
+ var d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: function () { return e[k]; }
18
+ });
19
+ }
20
+ });
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+
26
+ var React9__namespace = /*#__PURE__*/_interopNamespace(React9);
27
+
28
+ // src/skeletons/LoginTemplate.tsx
29
+ var ALIGN_MAP = {
30
+ start: "flex-start",
31
+ center: "center",
32
+ end: "flex-end",
33
+ stretch: "stretch"
34
+ };
35
+ var JUSTIFY_MAP = {
36
+ start: "flex-start",
37
+ center: "center",
38
+ end: "flex-end",
39
+ between: "space-between",
40
+ around: "space-around"
41
+ };
42
+ function toCssSpacing(spacing) {
43
+ if (typeof spacing === "number") return `${spacing}px`;
44
+ if (spacing === "sm" || spacing === "md" || spacing === "lg") {
45
+ return `var(--iris-gap-${spacing})`;
46
+ }
47
+ return spacing;
48
+ }
49
+ var IrisStack = React9__namespace.forwardRef(function IrisStack2({
50
+ direction = "column",
51
+ spacing = "md",
52
+ align = "stretch",
53
+ justify = "start",
54
+ wrap = false,
55
+ inline = false,
56
+ style,
57
+ children,
58
+ ...rest
59
+ }, ref) {
60
+ return /* @__PURE__ */ jsxRuntime.jsx(
61
+ "div",
62
+ {
63
+ ...rest,
64
+ ref,
65
+ "data-iris-stack": "",
66
+ "data-iris-stack-direction": direction,
67
+ style: {
68
+ display: inline ? "inline-flex" : "flex",
69
+ flexDirection: direction,
70
+ gap: toCssSpacing(spacing),
71
+ alignItems: ALIGN_MAP[align],
72
+ justifyContent: JUSTIFY_MAP[justify],
73
+ flexWrap: wrap ? "wrap" : "nowrap",
74
+ ...style
75
+ },
76
+ children
77
+ }
78
+ );
79
+ });
80
+ var WIDTH_MAP = {
81
+ sm: "640px",
82
+ md: "768px",
83
+ lg: "1024px",
84
+ xl: "1280px",
85
+ full: "100%"
86
+ };
87
+ function resolveMaxWidth(input) {
88
+ if (input === "sm" || input === "md" || input === "lg" || input === "xl" || input === "full") {
89
+ return WIDTH_MAP[input];
90
+ }
91
+ return input;
92
+ }
93
+ function resolvePadding(input) {
94
+ if (typeof input === "number") return `${input}px`;
95
+ if (input === "sm" || input === "md" || input === "lg") {
96
+ return `var(--iris-padding-${input})`;
97
+ }
98
+ return input;
99
+ }
100
+ var IrisContainer = React9__namespace.forwardRef(
101
+ function IrisContainer2({ maxWidth = "lg", padding = "md", center = true, style, children, ...rest }, ref) {
102
+ return /* @__PURE__ */ jsxRuntime.jsx(
103
+ "div",
104
+ {
105
+ ...rest,
106
+ ref,
107
+ "data-iris-container": "",
108
+ "data-iris-container-max-width": maxWidth,
109
+ style: {
110
+ width: "100%",
111
+ maxWidth: resolveMaxWidth(maxWidth),
112
+ padding: `0 ${resolvePadding(padding)}`,
113
+ ...center ? { marginInlineStart: "auto", marginInlineEnd: "auto" } : {},
114
+ ...style
115
+ },
116
+ children
117
+ }
118
+ );
119
+ }
120
+ );
121
+ var SIZE_MAP = {
122
+ sm: { padding: "4px 8px", fontSize: "12px", minHeight: "28px" },
123
+ md: { padding: "6px 12px", fontSize: "14px", minHeight: "34px" },
124
+ lg: { padding: "8px 12px", fontSize: "16px", minHeight: "40px" }
125
+ };
126
+ var IrisInput = React9__namespace.forwardRef(function IrisInput2({
127
+ size = "md",
128
+ type = "text",
129
+ invalid = false,
130
+ ariaDescribedby,
131
+ prefix,
132
+ suffix,
133
+ style,
134
+ onFocus,
135
+ onBlur,
136
+ ...rest
137
+ }, ref) {
138
+ const [focused, setFocused] = React9__namespace.useState(false);
139
+ const sizeStyles = SIZE_MAP[size];
140
+ const borderColor = invalid ? "var(--iris-danger)" : focused ? "var(--iris-primary)" : "var(--iris-border)";
141
+ const boxShadow = focused ? `0 0 0 3px ${invalid ? "rgba(239, 68, 68, 0.18)" : "rgba(99, 102, 241, 0.18)"}` : "none";
142
+ const wrapperStyle = {
143
+ display: "inline-flex",
144
+ alignItems: "center",
145
+ gap: "6px",
146
+ background: "var(--iris-background)",
147
+ color: "var(--iris-foreground)",
148
+ border: `1px solid ${borderColor}`,
149
+ borderRadius: "var(--iris-radius-md, 6px)",
150
+ cursor: rest.disabled ? "not-allowed" : "text",
151
+ opacity: rest.disabled ? 0.6 : 1,
152
+ transition: "border-color 120ms ease, box-shadow 120ms ease",
153
+ boxShadow,
154
+ padding: sizeStyles.padding,
155
+ minHeight: sizeStyles.minHeight,
156
+ fontSize: sizeStyles.fontSize,
157
+ ...style
158
+ };
159
+ const inputStyle = {
160
+ flex: 1,
161
+ minWidth: 0,
162
+ border: "none",
163
+ outline: "none",
164
+ background: "transparent",
165
+ color: "inherit",
166
+ fontFamily: "inherit",
167
+ fontSize: "inherit",
168
+ padding: 0
169
+ };
170
+ return /* @__PURE__ */ jsxRuntime.jsxs(
171
+ "label",
172
+ {
173
+ "data-iris-input": "",
174
+ "data-iris-input-size": size,
175
+ "data-state": invalid ? "invalid" : focused ? "focused" : "idle",
176
+ style: wrapperStyle,
177
+ children: [
178
+ prefix ? /* @__PURE__ */ jsxRuntime.jsx(
179
+ "span",
180
+ {
181
+ "data-iris-input-prefix": "",
182
+ style: { display: "inline-flex", alignItems: "center", color: "var(--iris-muted)" },
183
+ children: prefix
184
+ }
185
+ ) : null,
186
+ /* @__PURE__ */ jsxRuntime.jsx(
187
+ "input",
188
+ {
189
+ ...rest,
190
+ ref,
191
+ type,
192
+ "aria-invalid": invalid ? "true" : void 0,
193
+ "aria-describedby": ariaDescribedby,
194
+ style: inputStyle,
195
+ onFocus: (e) => {
196
+ setFocused(true);
197
+ onFocus?.(e);
198
+ },
199
+ onBlur: (e) => {
200
+ setFocused(false);
201
+ onBlur?.(e);
202
+ }
203
+ }
204
+ ),
205
+ suffix ? /* @__PURE__ */ jsxRuntime.jsx(
206
+ "span",
207
+ {
208
+ "data-iris-input-suffix": "",
209
+ style: { display: "inline-flex", alignItems: "center", color: "var(--iris-muted)" },
210
+ children: suffix
211
+ }
212
+ ) : null
213
+ ]
214
+ }
215
+ );
216
+ });
217
+ var I18nContext = React9__namespace.createContext(null);
218
+ function useStore(store) {
219
+ return React9.useSyncExternalStore(
220
+ store.subscribe,
221
+ store.getState,
222
+ store.getState
223
+ // SSR fallback — same as client snapshot in our case.
224
+ );
225
+ }
226
+
227
+ // src/i18n/useI18n.ts
228
+ var fallbackI18n = null;
229
+ function getFallback() {
230
+ if (fallbackI18n === null) fallbackI18n = core.createI18n();
231
+ return fallbackI18n;
232
+ }
233
+ function useI18n() {
234
+ const ctx = React9__namespace.useContext(I18nContext);
235
+ const i18n = ctx ?? getFallback();
236
+ const state = useStore(i18n.store);
237
+ return {
238
+ locale: state.locale,
239
+ t: i18n.t,
240
+ formatDate: i18n.formatDate,
241
+ formatNumber: i18n.formatNumber,
242
+ formatRelativeTime: i18n.formatRelativeTime,
243
+ setLocale: i18n.setLocale,
244
+ setMessages: i18n.setMessages
245
+ };
246
+ }
247
+ var IrisPasswordInput = React9__namespace.forwardRef(
248
+ function IrisPasswordInput2({ showToggle = true, suffix, prefix, disabled, readOnly, ...rest }, ref) {
249
+ const { t } = useI18n();
250
+ const [visible, setVisible] = React9__namespace.useState(false);
251
+ const toggle = () => {
252
+ if (disabled || readOnly) return;
253
+ setVisible((v) => !v);
254
+ };
255
+ const toggleBtn = showToggle ? /* @__PURE__ */ jsxRuntime.jsx(
256
+ "button",
257
+ {
258
+ type: "button",
259
+ "data-iris-password-input-toggle": "",
260
+ "aria-label": visible ? t("passwordInput.hide") : t("passwordInput.show"),
261
+ "aria-pressed": visible ? "true" : "false",
262
+ onClick: toggle,
263
+ style: {
264
+ background: "transparent",
265
+ border: "none",
266
+ cursor: disabled ? "not-allowed" : "pointer",
267
+ color: "var(--iris-muted)",
268
+ padding: "0 2px",
269
+ fontSize: 13,
270
+ lineHeight: 1
271
+ },
272
+ children: visible ? "\u{1F648}" : "\u{1F441}"
273
+ }
274
+ ) : null;
275
+ return /* @__PURE__ */ jsxRuntime.jsx(
276
+ IrisInput,
277
+ {
278
+ ...rest,
279
+ ref,
280
+ type: visible ? "text" : "password",
281
+ disabled,
282
+ readOnly,
283
+ prefix,
284
+ suffix: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
285
+ suffix,
286
+ toggleBtn
287
+ ] }),
288
+ "data-iris-password-input": ""
289
+ }
290
+ );
291
+ }
292
+ );
293
+ var DIM_MAP = {
294
+ sm: "14px",
295
+ md: "18px",
296
+ lg: "22px"
297
+ };
298
+ var IrisCheckbox = React9__namespace.forwardRef(
299
+ function IrisCheckbox2({
300
+ checked,
301
+ defaultChecked = false,
302
+ onChange,
303
+ size = "md",
304
+ disabled = false,
305
+ invalid = false,
306
+ ariaDescribedby,
307
+ children,
308
+ style,
309
+ ...rest
310
+ }, ref) {
311
+ const [internalChecked, setInternalChecked] = React9__namespace.useState(defaultChecked);
312
+ const isControlled = checked !== void 0;
313
+ const value = isControlled ? checked : internalChecked;
314
+ const innerRef = React9__namespace.useRef(null);
315
+ React9__namespace.useImperativeHandle(ref, () => innerRef.current, []);
316
+ React9__namespace.useEffect(() => {
317
+ const el = innerRef.current;
318
+ if (el) el.indeterminate = value === "indeterminate";
319
+ }, [value]);
320
+ const handleChange = (e) => {
321
+ if (disabled) return;
322
+ const next = e.target.checked;
323
+ if (!isControlled) setInternalChecked(next);
324
+ onChange?.(next, e);
325
+ };
326
+ const state = value === "indeterminate" ? "indeterminate" : value ? "checked" : "unchecked";
327
+ const dim = DIM_MAP[size];
328
+ const boxStyle = {
329
+ display: "inline-flex",
330
+ alignItems: "center",
331
+ justifyContent: "center",
332
+ width: dim,
333
+ height: dim,
334
+ borderRadius: "var(--iris-radius-sm, 4px)",
335
+ border: `1px solid ${state === "unchecked" ? "var(--iris-border)" : "var(--iris-primary)"}`,
336
+ background: state === "unchecked" ? "var(--iris-background)" : "var(--iris-primary)",
337
+ color: "var(--iris-primary-foreground, #fff)",
338
+ cursor: disabled ? "not-allowed" : "pointer",
339
+ opacity: disabled ? 0.6 : 1,
340
+ transition: "background-color 120ms ease, border-color 120ms ease",
341
+ flexShrink: 0
342
+ };
343
+ const indicator = state === "checked" ? "\u2713" : state === "indeterminate" ? "\u2014" : null;
344
+ return /* @__PURE__ */ jsxRuntime.jsxs(
345
+ "label",
346
+ {
347
+ "data-iris-checkbox": "",
348
+ "data-iris-checkbox-size": size,
349
+ "data-state": state,
350
+ style: {
351
+ display: "inline-flex",
352
+ alignItems: "center",
353
+ gap: 8,
354
+ cursor: disabled ? "not-allowed" : "pointer",
355
+ userSelect: "none",
356
+ ...style
357
+ },
358
+ children: [
359
+ /* @__PURE__ */ jsxRuntime.jsx(
360
+ "input",
361
+ {
362
+ ...rest,
363
+ ref: innerRef,
364
+ type: "checkbox",
365
+ checked: value === true,
366
+ disabled,
367
+ "aria-checked": state === "indeterminate" ? "mixed" : state === "checked" ? "true" : "false",
368
+ "aria-describedby": ariaDescribedby,
369
+ "aria-invalid": invalid ? "true" : void 0,
370
+ onChange: handleChange,
371
+ style: {
372
+ position: "absolute",
373
+ opacity: 0,
374
+ width: 0,
375
+ height: 0,
376
+ pointerEvents: "none"
377
+ }
378
+ }
379
+ ),
380
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", style: boxStyle, children: indicator }),
381
+ children
382
+ ]
383
+ }
384
+ );
385
+ }
386
+ );
387
+
388
+ // src/primitives/button/styles.ts
389
+ var STYLE_ID = "iris-button-styles";
390
+ var CSS = `
391
+ .iris-button {
392
+ cursor: pointer;
393
+ display: inline-flex;
394
+ align-items: center;
395
+ justify-content: center;
396
+ gap: var(--iris-gap-sm, 4px);
397
+ font-family: inherit;
398
+ font-weight: 500;
399
+ line-height: 1.2;
400
+ border-radius: var(--iris-radius-md, 6px);
401
+ white-space: nowrap;
402
+ user-select: none;
403
+ position: relative;
404
+ transition:
405
+ background-color 120ms ease,
406
+ border-color 120ms ease,
407
+ color 120ms ease,
408
+ filter 120ms ease;
409
+ }
410
+ .iris-button:focus-visible {
411
+ outline: 2px solid var(--iris-primary);
412
+ outline-offset: 2px;
413
+ }
414
+ .iris-button[disabled],
415
+ .iris-button[aria-busy="true"] {
416
+ cursor: not-allowed;
417
+ opacity: 0.6;
418
+ }
419
+ .iris-button[data-iris-button-variant="solid"]:not([disabled]):not([aria-busy="true"]):hover {
420
+ filter: brightness(1.08);
421
+ }
422
+ .iris-button[data-iris-button-variant="outline"]:not([disabled]):not([aria-busy="true"]):hover,
423
+ .iris-button[data-iris-button-variant="ghost"]:not([disabled]):not([aria-busy="true"]):hover {
424
+ background-color: var(--iris-surface-hover);
425
+ }
426
+ .iris-button[data-iris-button-variant="link"]:not([disabled]):not([aria-busy="true"]):hover {
427
+ text-decoration: underline;
428
+ }
429
+ .iris-button-leading {
430
+ display: inline-flex;
431
+ align-items: center;
432
+ }
433
+ .iris-button-spinner {
434
+ width: 1em;
435
+ height: 1em;
436
+ display: inline-block;
437
+ animation: iris-button-spin 0.7s linear infinite;
438
+ }
439
+ @keyframes iris-button-spin {
440
+ to { transform: rotate(360deg); }
441
+ }
442
+ `;
443
+ var installed = false;
444
+ function installButtonStyles() {
445
+ if (installed) return;
446
+ if (typeof document === "undefined") return;
447
+ if (document.getElementById(STYLE_ID)) {
448
+ installed = true;
449
+ return;
450
+ }
451
+ const style = document.createElement("style");
452
+ style.id = STYLE_ID;
453
+ style.textContent = CSS;
454
+ document.head.appendChild(style);
455
+ installed = true;
456
+ }
457
+ var SIZE_STYLES = {
458
+ sm: { padding: "var(--iris-padding-sm) var(--iris-padding-md)", fontSize: "12px" },
459
+ md: { padding: "var(--iris-padding-sm) var(--iris-padding-lg)", fontSize: "14px" },
460
+ lg: { padding: "var(--iris-padding-md) var(--iris-padding-lg)", fontSize: "16px" }
461
+ };
462
+ var VARIANT_STYLES = {
463
+ solid: {
464
+ background: "var(--iris-primary)",
465
+ color: "var(--iris-primary-foreground)",
466
+ border: "1px solid var(--iris-primary)"
467
+ },
468
+ outline: {
469
+ background: "transparent",
470
+ color: "var(--iris-primary)",
471
+ border: "1px solid var(--iris-border)"
472
+ },
473
+ ghost: {
474
+ background: "transparent",
475
+ color: "var(--iris-foreground)",
476
+ border: "1px solid transparent"
477
+ },
478
+ link: {
479
+ background: "transparent",
480
+ color: "var(--iris-primary)",
481
+ border: "1px solid transparent",
482
+ textDecoration: "none"
483
+ }
484
+ };
485
+ function buildInlineStyle(variant, size) {
486
+ const base = { ...SIZE_STYLES[size], ...VARIANT_STYLES[variant] };
487
+ if (variant === "link") base.padding = "0";
488
+ return base;
489
+ }
490
+ function Spinner() {
491
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "iris-button-spinner", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
492
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeOpacity: "0.25", strokeWidth: "3" }),
493
+ /* @__PURE__ */ jsxRuntime.jsx(
494
+ "path",
495
+ {
496
+ d: "M22 12a10 10 0 0 1-10 10",
497
+ stroke: "currentColor",
498
+ strokeWidth: "3",
499
+ strokeLinecap: "round"
500
+ }
501
+ )
502
+ ] });
503
+ }
504
+ function IrisButton({
505
+ variant = "solid",
506
+ size = "md",
507
+ disabled = false,
508
+ loading = false,
509
+ type = "button",
510
+ asChild = false,
511
+ leading,
512
+ children,
513
+ className,
514
+ style,
515
+ onClick,
516
+ ...rest
517
+ }) {
518
+ React9.useEffect(() => {
519
+ installButtonStyles();
520
+ }, []);
521
+ const isInteractive = !disabled && !loading;
522
+ const handleClick = (event) => {
523
+ if (!isInteractive) {
524
+ event.preventDefault();
525
+ event.stopPropagation();
526
+ return;
527
+ }
528
+ onClick?.(event);
529
+ };
530
+ const baseProps = {
531
+ className: ["iris-button", className].filter(Boolean).join(" "),
532
+ "data-iris-button-variant": variant,
533
+ "data-iris-button-size": size,
534
+ "aria-disabled": disabled ? "true" : void 0,
535
+ "aria-busy": loading ? "true" : void 0,
536
+ style: { ...buildInlineStyle(variant, size), ...style ?? {} }
537
+ };
538
+ if (asChild) {
539
+ const only = React9.Children.only(children);
540
+ if (!only || !React9.isValidElement(only)) {
541
+ if (typeof process === "undefined" || process.env?.NODE_ENV !== "production") {
542
+ console.warn("[iris-ui] IrisButton: as-child requires a single React element child");
543
+ }
544
+ return null;
545
+ }
546
+ const childProps = only.props;
547
+ return React9.cloneElement(only, {
548
+ ...rest,
549
+ ...baseProps,
550
+ className: [baseProps.className, childProps.className].filter(Boolean).join(" "),
551
+ style: { ...baseProps.style, ...childProps.style ?? {} },
552
+ onClick: core.composeEventHandlers(
553
+ handleClick,
554
+ childProps.onClick ?? (() => {
555
+ })
556
+ ),
557
+ ...isInteractive ? {} : { disabled: true }
558
+ });
559
+ }
560
+ return /* @__PURE__ */ jsxRuntime.jsxs("button", { ...rest, type, disabled: !isInteractive, onClick: handleClick, ...baseProps, children: [
561
+ (loading || leading) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "iris-button-leading", children: loading ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) : leading }),
562
+ children
563
+ ] });
564
+ }
565
+ var IrisFormField = React9__namespace.forwardRef(
566
+ function IrisFormField2({ label, hint, error, required = false, labelFor, size = "md", style, children, ...rest }, ref) {
567
+ const generated = React9__namespace.useId();
568
+ const controlId = labelFor || `${generated}-control`;
569
+ const hintId = `${generated}-hint`;
570
+ const errorId = `${generated}-error`;
571
+ const describedBy = React9__namespace.useMemo(() => {
572
+ const ids = [];
573
+ if (hint && !error) ids.push(hintId);
574
+ if (error) ids.push(errorId);
575
+ return ids.length > 0 ? ids.join(" ") : void 0;
576
+ }, [hint, error, hintId, errorId]);
577
+ let injected = false;
578
+ const decorated = React9__namespace.Children.map(children, (child) => {
579
+ if (!injected && React9__namespace.isValidElement(child)) {
580
+ injected = true;
581
+ const injectedProps = {
582
+ id: controlId,
583
+ invalid: error ? true : void 0,
584
+ ariaDescribedby: describedBy
585
+ };
586
+ return React9__namespace.cloneElement(child, injectedProps);
587
+ }
588
+ return child;
589
+ });
590
+ const labelStyle = {
591
+ fontSize: size === "sm" ? "12px" : "14px",
592
+ fontWeight: 500,
593
+ color: error ? "var(--iris-danger)" : "var(--iris-foreground)",
594
+ display: "inline-flex",
595
+ alignItems: "center",
596
+ gap: "4px"
597
+ };
598
+ return /* @__PURE__ */ jsxRuntime.jsxs(
599
+ "div",
600
+ {
601
+ ...rest,
602
+ ref,
603
+ "data-iris-form-field": "",
604
+ "data-iris-form-field-state": error ? "invalid" : "valid",
605
+ style: {
606
+ display: "flex",
607
+ flexDirection: "column",
608
+ gap: "4px",
609
+ ...style
610
+ },
611
+ children: [
612
+ label ? /* @__PURE__ */ jsxRuntime.jsxs("label", { htmlFor: controlId, "data-iris-form-field-label": "", style: labelStyle, children: [
613
+ label,
614
+ required ? /* @__PURE__ */ jsxRuntime.jsx(
615
+ "span",
616
+ {
617
+ "aria-hidden": "true",
618
+ "data-iris-form-field-required": "",
619
+ style: { color: "var(--iris-danger)" },
620
+ children: "*"
621
+ }
622
+ ) : null
623
+ ] }) : null,
624
+ decorated,
625
+ hint && !error ? /* @__PURE__ */ jsxRuntime.jsx(
626
+ "div",
627
+ {
628
+ id: hintId,
629
+ "data-iris-form-field-hint": "",
630
+ style: { fontSize: 12, color: "var(--iris-muted)" },
631
+ children: hint
632
+ }
633
+ ) : null,
634
+ error ? /* @__PURE__ */ jsxRuntime.jsx(
635
+ "div",
636
+ {
637
+ id: errorId,
638
+ "data-iris-form-field-error": "",
639
+ role: "alert",
640
+ style: { fontSize: 12, color: "var(--iris-danger)" },
641
+ children: error
642
+ }
643
+ ) : null
644
+ ]
645
+ }
646
+ );
647
+ }
648
+ );
649
+ var TONE_TO_VAR = {
650
+ info: "--iris-primary",
651
+ success: "--iris-success",
652
+ warning: "--iris-warning",
653
+ danger: "--iris-danger"
654
+ };
655
+ function IrisAlert({
656
+ tone = "info",
657
+ title,
658
+ closable = false,
659
+ open,
660
+ onClose,
661
+ icon,
662
+ children,
663
+ style,
664
+ ...rest
665
+ }) {
666
+ const { t } = useI18n();
667
+ const [internalOpen, setInternalOpen] = React9__namespace.useState(true);
668
+ React9__namespace.useEffect(() => {
669
+ if (open !== void 0) setInternalOpen(open);
670
+ }, [open]);
671
+ const isOpen = open !== void 0 ? open : internalOpen;
672
+ if (!isOpen) return null;
673
+ const tonalVar = `var(${TONE_TO_VAR[tone]})`;
674
+ const handleClose = () => {
675
+ if (open === void 0) setInternalOpen(false);
676
+ onClose?.();
677
+ };
678
+ return /* @__PURE__ */ jsxRuntime.jsxs(
679
+ "div",
680
+ {
681
+ ...rest,
682
+ role: tone === "danger" || tone === "warning" ? "alert" : "status",
683
+ "data-iris-alert": "",
684
+ "data-iris-alert-tone": tone,
685
+ style: {
686
+ display: "flex",
687
+ gap: "var(--iris-gap-md, 12px)",
688
+ padding: "var(--iris-padding-md, 12px)",
689
+ borderRadius: "var(--iris-radius-md, 6px)",
690
+ border: `1px solid ${tonalVar}`,
691
+ // `backgroundColor` is the precomputed fallback under color-mix (engines
692
+ // without it); the `background` shorthand overrides with the exact mix.
693
+ backgroundColor: `var(${TONE_TO_VAR[tone]}-subtle)`,
694
+ background: `color-mix(in srgb, ${tonalVar} 10%, var(--iris-background))`,
695
+ color: "var(--iris-foreground)",
696
+ alignItems: "flex-start",
697
+ ...style
698
+ },
699
+ children: [
700
+ icon ? /* @__PURE__ */ jsxRuntime.jsx(
701
+ "span",
702
+ {
703
+ "data-iris-alert-icon": "",
704
+ style: { color: tonalVar, flexShrink: 0, display: "inline-flex" },
705
+ children: icon
706
+ }
707
+ ) : null,
708
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-iris-alert-body": "", style: { flex: 1, minWidth: 0 }, children: [
709
+ title ? /* @__PURE__ */ jsxRuntime.jsx(
710
+ "div",
711
+ {
712
+ "data-iris-alert-title": "",
713
+ style: { fontWeight: 600, marginBottom: 4, color: tonalVar },
714
+ children: title
715
+ }
716
+ ) : null,
717
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-iris-alert-content": "", children })
718
+ ] }),
719
+ closable ? /* @__PURE__ */ jsxRuntime.jsx(
720
+ "button",
721
+ {
722
+ type: "button",
723
+ "data-iris-alert-close": "",
724
+ "aria-label": t("alert.close"),
725
+ onClick: handleClose,
726
+ style: {
727
+ background: "transparent",
728
+ border: "none",
729
+ cursor: "pointer",
730
+ color: "var(--iris-muted)",
731
+ fontSize: 16,
732
+ padding: 0,
733
+ lineHeight: 1,
734
+ flexShrink: 0
735
+ },
736
+ children: "\u2715"
737
+ }
738
+ ) : null
739
+ ]
740
+ }
741
+ );
742
+ }
743
+ var SPACING_MAP = {
744
+ sm: "8px",
745
+ md: "16px",
746
+ lg: "24px"
747
+ };
748
+ function IrisDivider({
749
+ orientation = "horizontal",
750
+ label,
751
+ spacing = "md",
752
+ children,
753
+ style,
754
+ ...rest
755
+ }) {
756
+ const isHorizontal = orientation === "horizontal";
757
+ const hasLabel = Boolean(label || children);
758
+ if (isHorizontal && !hasLabel) {
759
+ return /* @__PURE__ */ jsxRuntime.jsx(
760
+ "hr",
761
+ {
762
+ ...rest,
763
+ "data-iris-divider": "",
764
+ "data-iris-divider-orientation": "horizontal",
765
+ style: {
766
+ border: "none",
767
+ borderTop: "1px solid var(--iris-border)",
768
+ margin: `${SPACING_MAP[spacing]} 0`,
769
+ width: "100%",
770
+ ...style
771
+ }
772
+ }
773
+ );
774
+ }
775
+ if (!isHorizontal) {
776
+ return /* @__PURE__ */ jsxRuntime.jsx(
777
+ "div",
778
+ {
779
+ ...rest,
780
+ role: "separator",
781
+ "aria-orientation": "vertical",
782
+ "data-iris-divider": "",
783
+ "data-iris-divider-orientation": "vertical",
784
+ style: {
785
+ display: "inline-block",
786
+ width: 1,
787
+ alignSelf: "stretch",
788
+ background: "var(--iris-border)",
789
+ margin: `0 ${SPACING_MAP[spacing]}`,
790
+ ...style
791
+ }
792
+ }
793
+ );
794
+ }
795
+ return /* @__PURE__ */ jsxRuntime.jsxs(
796
+ "div",
797
+ {
798
+ ...rest,
799
+ role: "separator",
800
+ "aria-orientation": "horizontal",
801
+ "data-iris-divider": "",
802
+ "data-iris-divider-orientation": "horizontal",
803
+ "data-iris-divider-has-label": "true",
804
+ style: {
805
+ display: "flex",
806
+ alignItems: "center",
807
+ gap: 8,
808
+ margin: `${SPACING_MAP[spacing]} 0`,
809
+ color: "var(--iris-muted)",
810
+ fontSize: 12,
811
+ textTransform: "uppercase",
812
+ letterSpacing: "0.04em",
813
+ ...style
814
+ },
815
+ children: [
816
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-iris-divider-line": "before", style: lineStyle }),
817
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-iris-divider-label": "", children: children ?? label }),
818
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "data-iris-divider-line": "after", style: lineStyle })
819
+ ]
820
+ }
821
+ );
822
+ }
823
+ var lineStyle = {
824
+ flex: 1,
825
+ height: 1,
826
+ background: "var(--iris-border)"
827
+ };
828
+ function IrisLoginTemplate({
829
+ title = "Sign in",
830
+ description = "",
831
+ showRemember = true,
832
+ error = "",
833
+ submitLabel = "Sign in",
834
+ loading = false,
835
+ header,
836
+ forgot,
837
+ footer,
838
+ onSubmit,
839
+ style,
840
+ className
841
+ }) {
842
+ const [email, setEmail] = React9__namespace.useState("");
843
+ const [password, setPassword] = React9__namespace.useState("");
844
+ const [remember, setRemember] = React9__namespace.useState(false);
845
+ const handleSubmit = (e) => {
846
+ e.preventDefault();
847
+ onSubmit?.({ email, password, remember });
848
+ };
849
+ return /* @__PURE__ */ jsxRuntime.jsx(
850
+ "div",
851
+ {
852
+ "data-iris-login-template": "",
853
+ className,
854
+ style: {
855
+ minHeight: "100vh",
856
+ display: "flex",
857
+ alignItems: "center",
858
+ justifyContent: "center",
859
+ background: "var(--iris-background)",
860
+ color: "var(--iris-foreground)",
861
+ padding: 24,
862
+ ...style
863
+ },
864
+ children: /* @__PURE__ */ jsxRuntime.jsx(IrisContainer, { maxWidth: "420px", padding: 0, children: /* @__PURE__ */ jsxRuntime.jsx(
865
+ "form",
866
+ {
867
+ onSubmit: handleSubmit,
868
+ "data-iris-login-form": "",
869
+ style: {
870
+ background: "var(--iris-surface)",
871
+ border: "1px solid var(--iris-border)",
872
+ borderRadius: "var(--iris-radius-lg, 8px)",
873
+ padding: 32,
874
+ boxShadow: "0 6px 20px -8px rgba(0, 0, 0, 0.16)"
875
+ },
876
+ children: /* @__PURE__ */ jsxRuntime.jsxs(IrisStack, { spacing: "lg", children: [
877
+ header ?? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
878
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { margin: "0 0 4px 0", fontSize: 22, fontWeight: 700 }, children: title }),
879
+ description ? /* @__PURE__ */ jsxRuntime.jsx(
880
+ "p",
881
+ {
882
+ style: {
883
+ margin: 0,
884
+ color: "var(--iris-muted)",
885
+ fontSize: 14
886
+ },
887
+ children: description
888
+ }
889
+ ) : null
890
+ ] }),
891
+ error ? /* @__PURE__ */ jsxRuntime.jsx(IrisAlert, { tone: "danger", title: error }) : null,
892
+ /* @__PURE__ */ jsxRuntime.jsx(IrisFormField, { label: "Email", required: true, children: /* @__PURE__ */ jsxRuntime.jsx(
893
+ IrisInput,
894
+ {
895
+ type: "email",
896
+ value: email,
897
+ onChange: (e) => setEmail(e.target.value),
898
+ placeholder: "you@example.com",
899
+ disabled: loading,
900
+ autoComplete: "email"
901
+ }
902
+ ) }),
903
+ /* @__PURE__ */ jsxRuntime.jsx(IrisFormField, { label: "Password", required: true, children: /* @__PURE__ */ jsxRuntime.jsx(
904
+ IrisPasswordInput,
905
+ {
906
+ value: password,
907
+ onChange: (e) => setPassword(e.target.value),
908
+ placeholder: "Enter your password",
909
+ disabled: loading,
910
+ autoComplete: "current-password"
911
+ }
912
+ ) }),
913
+ showRemember ? /* @__PURE__ */ jsxRuntime.jsxs(
914
+ "div",
915
+ {
916
+ style: {
917
+ display: "flex",
918
+ alignItems: "center",
919
+ justifyContent: "space-between"
920
+ },
921
+ children: [
922
+ /* @__PURE__ */ jsxRuntime.jsx(
923
+ IrisCheckbox,
924
+ {
925
+ checked: remember,
926
+ onChange: (next) => setRemember(next),
927
+ disabled: loading,
928
+ children: "Remember me"
929
+ }
930
+ ),
931
+ forgot ?? null
932
+ ]
933
+ }
934
+ ) : null,
935
+ /* @__PURE__ */ jsxRuntime.jsx(IrisButton, { type: "submit", variant: "solid", loading, style: { width: "100%" }, children: submitLabel }),
936
+ footer ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
937
+ /* @__PURE__ */ jsxRuntime.jsx(IrisDivider, { spacing: "md", label: "or" }),
938
+ footer
939
+ ] }) : null
940
+ ] })
941
+ }
942
+ ) })
943
+ }
944
+ );
945
+ }
946
+ function asLen(v) {
947
+ return typeof v === "number" ? `${v}px` : v;
948
+ }
949
+ function IrisSidebarLayout({
950
+ collapsed: collapsedProp,
951
+ defaultCollapsed = false,
952
+ onCollapsedChange,
953
+ width = 240,
954
+ collapsedWidth = 60,
955
+ side = "left",
956
+ sidebar,
957
+ style,
958
+ children,
959
+ ...rest
960
+ }) {
961
+ const isControlled = collapsedProp !== void 0;
962
+ const [internal, setInternal] = React9__namespace.useState(defaultCollapsed);
963
+ const collapsed = isControlled ? Boolean(collapsedProp) : internal;
964
+ const setCollapsed = React9__namespace.useCallback(
965
+ (next) => {
966
+ if (!isControlled) setInternal(next);
967
+ onCollapsedChange?.(next);
968
+ },
969
+ [isControlled, onCollapsedChange]
970
+ );
971
+ const sidebarContent = typeof sidebar === "function" ? sidebar({
972
+ collapsed,
973
+ setCollapsed
974
+ }) : sidebar;
975
+ const sidebarStyle = {
976
+ width: collapsed ? asLen(collapsedWidth) : asLen(width),
977
+ flexShrink: 0,
978
+ background: "var(--iris-surface)",
979
+ borderRight: side === "left" ? "1px solid var(--iris-border)" : "none",
980
+ borderLeft: side === "right" ? "1px solid var(--iris-border)" : "none",
981
+ transition: "width 180ms ease",
982
+ overflow: "hidden",
983
+ display: "flex",
984
+ flexDirection: "column"
985
+ };
986
+ return /* @__PURE__ */ jsxRuntime.jsxs(
987
+ "div",
988
+ {
989
+ ...rest,
990
+ "data-iris-sidebar-layout": "",
991
+ "data-collapsed": collapsed ? "" : void 0,
992
+ "data-side": side,
993
+ style: {
994
+ display: "flex",
995
+ flexDirection: side === "right" ? "row-reverse" : "row",
996
+ width: "100%",
997
+ height: "100%",
998
+ minHeight: 0,
999
+ color: "var(--iris-foreground)",
1000
+ ...style
1001
+ },
1002
+ children: [
1003
+ /* @__PURE__ */ jsxRuntime.jsx(
1004
+ "aside",
1005
+ {
1006
+ role: "complementary",
1007
+ "data-iris-sidebar": "",
1008
+ "data-collapsed": collapsed ? "" : void 0,
1009
+ style: sidebarStyle,
1010
+ children: sidebarContent
1011
+ }
1012
+ ),
1013
+ /* @__PURE__ */ jsxRuntime.jsx(
1014
+ "div",
1015
+ {
1016
+ "data-iris-sidebar-main": "",
1017
+ style: {
1018
+ flex: 1,
1019
+ minWidth: 0,
1020
+ overflow: "auto",
1021
+ background: "var(--iris-background)"
1022
+ },
1023
+ children
1024
+ }
1025
+ )
1026
+ ]
1027
+ }
1028
+ );
1029
+ }
1030
+ function asLen2(v) {
1031
+ return typeof v === "number" ? `${v}px` : v;
1032
+ }
1033
+ function IrisHeaderLayout({
1034
+ headerHeight = "auto",
1035
+ footerHeight = "auto",
1036
+ sticky = true,
1037
+ header,
1038
+ footer,
1039
+ style,
1040
+ children,
1041
+ ...rest
1042
+ }) {
1043
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1044
+ "div",
1045
+ {
1046
+ ...rest,
1047
+ "data-iris-header-layout": "",
1048
+ style: {
1049
+ display: "flex",
1050
+ flexDirection: "column",
1051
+ width: "100%",
1052
+ height: "100%",
1053
+ minHeight: 0,
1054
+ background: "var(--iris-background)",
1055
+ color: "var(--iris-foreground)",
1056
+ ...style
1057
+ },
1058
+ children: [
1059
+ header ? /* @__PURE__ */ jsxRuntime.jsx(
1060
+ "header",
1061
+ {
1062
+ role: "banner",
1063
+ "data-iris-header": "",
1064
+ style: {
1065
+ flexShrink: 0,
1066
+ height: asLen2(headerHeight),
1067
+ borderBottom: "1px solid var(--iris-border)",
1068
+ background: "var(--iris-surface)",
1069
+ position: sticky ? "sticky" : "static",
1070
+ top: 0,
1071
+ zIndex: 50
1072
+ },
1073
+ children: header
1074
+ }
1075
+ ) : null,
1076
+ /* @__PURE__ */ jsxRuntime.jsx(
1077
+ "main",
1078
+ {
1079
+ role: "main",
1080
+ "data-iris-header-main": "",
1081
+ style: { flex: 1, minHeight: 0, overflow: "auto" },
1082
+ children
1083
+ }
1084
+ ),
1085
+ footer ? /* @__PURE__ */ jsxRuntime.jsx(
1086
+ "footer",
1087
+ {
1088
+ role: "contentinfo",
1089
+ "data-iris-footer": "",
1090
+ style: {
1091
+ flexShrink: 0,
1092
+ height: asLen2(footerHeight),
1093
+ borderTop: "1px solid var(--iris-border)",
1094
+ background: "var(--iris-surface)"
1095
+ },
1096
+ children: footer
1097
+ }
1098
+ ) : null
1099
+ ]
1100
+ }
1101
+ );
1102
+ }
1103
+ function IrisDashboardGrid({
1104
+ columns = 12,
1105
+ gap = 16,
1106
+ minColWidth,
1107
+ style,
1108
+ children,
1109
+ ...rest
1110
+ }) {
1111
+ const gapCss = typeof gap === "number" ? `${gap}px` : gap;
1112
+ const gridTemplateColumns = minColWidth ? `repeat(auto-fill, minmax(${typeof minColWidth === "number" ? `${minColWidth}px` : minColWidth}, 1fr))` : `repeat(${columns}, 1fr)`;
1113
+ return /* @__PURE__ */ jsxRuntime.jsx(
1114
+ "div",
1115
+ {
1116
+ ...rest,
1117
+ "data-iris-dashboard-grid": "",
1118
+ style: {
1119
+ display: "grid",
1120
+ gap: gapCss,
1121
+ gridTemplateColumns,
1122
+ width: "100%",
1123
+ ...style
1124
+ },
1125
+ children
1126
+ }
1127
+ );
1128
+ }
1129
+ function IrisDashboardCard({
1130
+ colSpan = 1,
1131
+ rowSpan = 1,
1132
+ surface = true,
1133
+ style,
1134
+ children,
1135
+ ...rest
1136
+ }) {
1137
+ const gridColumn = colSpan === "full" ? "1 / -1" : `span ${colSpan}`;
1138
+ const gridRow = rowSpan > 1 ? `span ${rowSpan}` : void 0;
1139
+ return /* @__PURE__ */ jsxRuntime.jsx(
1140
+ "div",
1141
+ {
1142
+ ...rest,
1143
+ "data-iris-dashboard-card": "",
1144
+ style: {
1145
+ gridColumn,
1146
+ gridRow,
1147
+ background: surface ? "var(--iris-surface)" : "transparent",
1148
+ border: surface ? "1px solid var(--iris-border)" : "none",
1149
+ borderRadius: "var(--iris-radius-md, 6px)",
1150
+ padding: surface ? "var(--iris-padding-lg, 20px)" : 0,
1151
+ minWidth: 0,
1152
+ ...style
1153
+ },
1154
+ children
1155
+ }
1156
+ );
1157
+ }
1158
+ function IrisDashboardTemplate({
1159
+ title = "Dashboard",
1160
+ sidebarTitle = "",
1161
+ nav = [],
1162
+ activeId = "",
1163
+ onActiveIdChange,
1164
+ cards = [],
1165
+ defaultCollapsed = false,
1166
+ onCollapsedChange,
1167
+ header,
1168
+ sidebarHeader,
1169
+ children,
1170
+ cardSlots,
1171
+ style,
1172
+ className
1173
+ }) {
1174
+ const [collapsed, setCollapsed] = React9__namespace.useState(defaultCollapsed);
1175
+ const handleCollapsed = (next) => {
1176
+ setCollapsed(next);
1177
+ onCollapsedChange?.(next);
1178
+ };
1179
+ return /* @__PURE__ */ jsxRuntime.jsx(
1180
+ "div",
1181
+ {
1182
+ "data-iris-dashboard-template": "",
1183
+ className,
1184
+ style: {
1185
+ width: "100%",
1186
+ height: "100vh",
1187
+ background: "var(--iris-background)",
1188
+ color: "var(--iris-foreground)",
1189
+ ...style
1190
+ },
1191
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1192
+ IrisSidebarLayout,
1193
+ {
1194
+ collapsed,
1195
+ onCollapsedChange: handleCollapsed,
1196
+ width: 240,
1197
+ collapsedWidth: 64,
1198
+ sidebar: (state) => /* @__PURE__ */ jsxRuntime.jsxs(IrisStack, { spacing: "sm", style: { padding: 12 }, children: [
1199
+ sidebarHeader ? sidebarHeader(state) : sidebarTitle ? /* @__PURE__ */ jsxRuntime.jsx(
1200
+ "div",
1201
+ {
1202
+ style: {
1203
+ padding: "8px 12px",
1204
+ fontSize: 14,
1205
+ fontWeight: 600,
1206
+ color: "var(--iris-foreground)",
1207
+ opacity: state.collapsed ? 0 : 1,
1208
+ transition: "opacity 120ms ease",
1209
+ whiteSpace: "nowrap",
1210
+ overflow: "hidden"
1211
+ },
1212
+ children: sidebarTitle
1213
+ }
1214
+ ) : null,
1215
+ /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Primary", style: { display: "flex", flexDirection: "column", gap: 2 }, children: nav.map((item) => {
1216
+ const isActive = item.id === activeId;
1217
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1218
+ "button",
1219
+ {
1220
+ type: "button",
1221
+ "data-iris-dashboard-nav-item": item.id,
1222
+ "data-iris-dashboard-nav-active": isActive ? "true" : void 0,
1223
+ onClick: () => onActiveIdChange?.(item.id),
1224
+ style: {
1225
+ display: "flex",
1226
+ alignItems: "center",
1227
+ gap: 10,
1228
+ padding: "8px 12px",
1229
+ background: isActive ? "var(--iris-primary)" : "transparent",
1230
+ color: isActive ? "var(--iris-primary-foreground, #fff)" : "var(--iris-foreground)",
1231
+ border: "none",
1232
+ borderRadius: "var(--iris-radius-sm, 4px)",
1233
+ cursor: "pointer",
1234
+ fontSize: 14,
1235
+ fontFamily: "inherit",
1236
+ textAlign: "start",
1237
+ outline: "none"
1238
+ },
1239
+ children: [
1240
+ item.icon ? /* @__PURE__ */ jsxRuntime.jsx(
1241
+ "span",
1242
+ {
1243
+ "aria-hidden": "true",
1244
+ style: { width: 16, display: "inline-flex", justifyContent: "center" },
1245
+ children: item.icon
1246
+ }
1247
+ ) : null,
1248
+ /* @__PURE__ */ jsxRuntime.jsx(
1249
+ "span",
1250
+ {
1251
+ style: {
1252
+ opacity: state.collapsed ? 0 : 1,
1253
+ transition: "opacity 120ms ease",
1254
+ whiteSpace: "nowrap"
1255
+ },
1256
+ children: item.label
1257
+ }
1258
+ )
1259
+ ]
1260
+ },
1261
+ item.id
1262
+ );
1263
+ }) })
1264
+ ] }),
1265
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1266
+ IrisHeaderLayout,
1267
+ {
1268
+ header: header ?? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "12px 20px", fontSize: 16, fontWeight: 600 }, children: title }),
1269
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: 20 }, children: /* @__PURE__ */ jsxRuntime.jsx(IrisDashboardGrid, { columns: 12, gap: 16, children: cards.map((card) => /* @__PURE__ */ jsxRuntime.jsxs(
1270
+ IrisDashboardCard,
1271
+ {
1272
+ colSpan: card.colSpan ?? 4,
1273
+ rowSpan: card.rowSpan ?? 1,
1274
+ "data-iris-dashboard-card-id": card.id,
1275
+ children: [
1276
+ /* @__PURE__ */ jsxRuntime.jsx(
1277
+ "h3",
1278
+ {
1279
+ style: {
1280
+ margin: "0 0 8px 0",
1281
+ fontSize: 14,
1282
+ fontWeight: 600,
1283
+ color: "var(--iris-foreground)"
1284
+ },
1285
+ children: card.title
1286
+ }
1287
+ ),
1288
+ cardSlots?.[card.id] !== void 0 ? cardSlots[card.id] : card.body ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, color: "var(--iris-muted)" }, children: card.body }) : null
1289
+ ]
1290
+ },
1291
+ card.id
1292
+ )) }) })
1293
+ }
1294
+ )
1295
+ }
1296
+ )
1297
+ }
1298
+ );
1299
+ }
1300
+
1301
+ exports.IrisDashboardTemplate = IrisDashboardTemplate;
1302
+ exports.IrisLoginTemplate = IrisLoginTemplate;
1303
+ //# sourceMappingURL=skeletons.cjs.map
1304
+ //# sourceMappingURL=skeletons.cjs.map