@mshuja288/aksuicore 0.2.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/dist/index.cjs ADDED
@@ -0,0 +1,1145 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var react = require('react');
6
+ var reactDom = require('react-dom');
7
+
8
+ // src/theme/tokens.ts
9
+ var aksuiTokens = {
10
+ brand: "#1E2735",
11
+ accent: "#E67E22",
12
+ ink: "#1E2735",
13
+ muted: "#667085",
14
+ line: "#e6e4df",
15
+ field: "#f6f5f3",
16
+ card: "#ffffff",
17
+ danger: "#b42318",
18
+ dangerBg: "#fff1f0",
19
+ ok: "#067647",
20
+ okBg: "#ecfdf3",
21
+ radius: "8px",
22
+ rowHeight: "34px",
23
+ tableHeaderHeight: "36px",
24
+ sideRailCollapsed: "52px",
25
+ sideRailExpanded: "280px",
26
+ previewPanelWidth: "300px"
27
+ };
28
+
29
+ // src/theme/index.ts
30
+ var aksuiThemeVersion = "0.2.0";
31
+ var variantClass = {
32
+ primary: "",
33
+ secondary: "secondary",
34
+ ghost: "ghost",
35
+ danger: "danger"
36
+ };
37
+ function Button({
38
+ variant = "primary",
39
+ className = "",
40
+ children,
41
+ ...props
42
+ }) {
43
+ const classes = ["aks-button", variantClass[variant], className].filter(Boolean).join(" ");
44
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: classes, ...props, children });
45
+ }
46
+ function Select({
47
+ value,
48
+ options,
49
+ onChange,
50
+ placeholder = "Select",
51
+ disabled = false,
52
+ required = false,
53
+ className = ""
54
+ }) {
55
+ const listId = react.useId();
56
+ const rootRef = react.useRef(null);
57
+ const menuRef = react.useRef(null);
58
+ const [open, setOpen] = react.useState(false);
59
+ const [menuPos, setMenuPos] = react.useState(null);
60
+ const selected = options.find((option) => option.value === value) ?? null;
61
+ function updatePosition() {
62
+ const root = rootRef.current;
63
+ if (!root) {
64
+ return;
65
+ }
66
+ const rect = root.getBoundingClientRect();
67
+ const spaceBelow = window.innerHeight - rect.bottom - 12;
68
+ const spaceAbove = rect.top - 12;
69
+ const openUp = spaceBelow < 220 && spaceAbove > spaceBelow;
70
+ const maxHeight = Math.max(160, Math.min(280, openUp ? spaceAbove : spaceBelow));
71
+ setMenuPos({
72
+ top: openUp ? rect.top - 8 : rect.bottom + 6,
73
+ left: rect.left,
74
+ width: rect.width,
75
+ maxHeight,
76
+ openUp
77
+ });
78
+ }
79
+ react.useLayoutEffect(() => {
80
+ if (!open) {
81
+ return;
82
+ }
83
+ updatePosition();
84
+ function onReposition() {
85
+ updatePosition();
86
+ }
87
+ window.addEventListener("resize", onReposition);
88
+ window.addEventListener("scroll", onReposition, true);
89
+ return () => {
90
+ window.removeEventListener("resize", onReposition);
91
+ window.removeEventListener("scroll", onReposition, true);
92
+ };
93
+ }, [open]);
94
+ react.useEffect(() => {
95
+ if (!open) {
96
+ return;
97
+ }
98
+ function onPointerDown(event) {
99
+ const target = event.target;
100
+ if (rootRef.current?.contains(target) || menuRef.current?.contains(target)) {
101
+ return;
102
+ }
103
+ setOpen(false);
104
+ }
105
+ function onKeyDown(event) {
106
+ if (event.key === "Escape") {
107
+ setOpen(false);
108
+ }
109
+ }
110
+ document.addEventListener("mousedown", onPointerDown);
111
+ document.addEventListener("keydown", onKeyDown);
112
+ return () => {
113
+ document.removeEventListener("mousedown", onPointerDown);
114
+ document.removeEventListener("keydown", onKeyDown);
115
+ };
116
+ }, [open]);
117
+ function choose(next) {
118
+ onChange(next);
119
+ setOpen(false);
120
+ }
121
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `app-select ${className}`.trim(), ref: rootRef, children: [
122
+ /* @__PURE__ */ jsxRuntime.jsx(
123
+ "input",
124
+ {
125
+ className: "app-select-mirror",
126
+ tabIndex: -1,
127
+ value,
128
+ required,
129
+ onChange: () => void 0,
130
+ "aria-hidden": "true"
131
+ }
132
+ ),
133
+ /* @__PURE__ */ jsxRuntime.jsxs(
134
+ "button",
135
+ {
136
+ type: "button",
137
+ className: open ? "app-select-trigger open" : "app-select-trigger",
138
+ disabled,
139
+ "aria-haspopup": "listbox",
140
+ "aria-expanded": open,
141
+ "aria-controls": listId,
142
+ onClick: () => {
143
+ if (!disabled) {
144
+ setOpen((current) => !current);
145
+ }
146
+ },
147
+ children: [
148
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: selected ? "app-select-value" : "app-select-placeholder", children: selected ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
149
+ selected.tone ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: `app-select-dot ${selected.tone}`, "aria-hidden": "true" }) : null,
150
+ selected.label
151
+ ] }) : placeholder }),
152
+ /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "app-select-chevron", viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 7.5 10 12.5 15 7.5", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) })
153
+ ]
154
+ }
155
+ ),
156
+ open && menuPos ? reactDom.createPortal(
157
+ /* @__PURE__ */ jsxRuntime.jsx(
158
+ "div",
159
+ {
160
+ ref: menuRef,
161
+ id: listId,
162
+ className: menuPos.openUp ? "app-select-menu open-up" : "app-select-menu",
163
+ role: "listbox",
164
+ style: {
165
+ top: menuPos.openUp ? void 0 : menuPos.top,
166
+ bottom: menuPos.openUp ? window.innerHeight - menuPos.top : void 0,
167
+ left: menuPos.left,
168
+ width: menuPos.width,
169
+ maxHeight: menuPos.maxHeight
170
+ },
171
+ children: options.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "app-select-empty", children: "No options" }) : options.map((option) => {
172
+ const active = option.value === value;
173
+ return /* @__PURE__ */ jsxRuntime.jsxs(
174
+ "button",
175
+ {
176
+ type: "button",
177
+ role: "option",
178
+ "aria-selected": active,
179
+ className: active ? "app-select-option active" : "app-select-option",
180
+ onClick: () => choose(option.value),
181
+ children: [
182
+ option.tone ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: `app-select-dot ${option.tone}`, "aria-hidden": "true" }) : null,
183
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label }),
184
+ active ? /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "app-select-check", viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.5 10.5 8.2 14.2 15.5 6", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) : null
185
+ ]
186
+ },
187
+ option.value || "__empty"
188
+ );
189
+ })
190
+ }
191
+ ),
192
+ document.body
193
+ ) : null
194
+ ] });
195
+ }
196
+ var AppSelect = Select;
197
+ var weekdayLabels = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
198
+ function pad(value) {
199
+ return String(value).padStart(2, "0");
200
+ }
201
+ function toIso(date) {
202
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
203
+ }
204
+ function parseIso(value) {
205
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
206
+ return null;
207
+ }
208
+ const [year, month, day] = value.split("-").map(Number);
209
+ const date = new Date(year, month - 1, day);
210
+ if (date.getFullYear() !== year || date.getMonth() !== month - 1 || date.getDate() !== day) {
211
+ return null;
212
+ }
213
+ return date;
214
+ }
215
+ function formatDisplay(value) {
216
+ const date = parseIso(value);
217
+ if (!date) {
218
+ return "";
219
+ }
220
+ return `${pad(date.getDate())}/${pad(date.getMonth() + 1)}/${date.getFullYear()}`;
221
+ }
222
+ function startOfMonth(date) {
223
+ return new Date(date.getFullYear(), date.getMonth(), 1);
224
+ }
225
+ function buildCells(month) {
226
+ const first = startOfMonth(month);
227
+ const mondayBased = (first.getDay() + 6) % 7;
228
+ const start = new Date(first);
229
+ start.setDate(first.getDate() - mondayBased);
230
+ return Array.from({ length: 42 }, (_, index) => {
231
+ const day = new Date(start);
232
+ day.setDate(start.getDate() + index);
233
+ return day;
234
+ });
235
+ }
236
+ function DateField({
237
+ value,
238
+ onChange,
239
+ placeholder = "dd/mm/yyyy",
240
+ disabled = false,
241
+ readOnly = false
242
+ }) {
243
+ const rootRef = react.useRef(null);
244
+ const menuRef = react.useRef(null);
245
+ const selected = parseIso(value);
246
+ const [open, setOpen] = react.useState(false);
247
+ const [menuPos, setMenuPos] = react.useState(null);
248
+ const [viewMonth, setViewMonth] = react.useState(() => startOfMonth(selected ?? /* @__PURE__ */ new Date()));
249
+ const cells = react.useMemo(() => buildCells(viewMonth), [viewMonth]);
250
+ const today = toIso(/* @__PURE__ */ new Date());
251
+ const locked = disabled || readOnly;
252
+ function updatePosition() {
253
+ const root = rootRef.current;
254
+ if (!root) {
255
+ return;
256
+ }
257
+ const rect = root.getBoundingClientRect();
258
+ const openUp = window.innerHeight - rect.bottom < 340 && rect.top > 340;
259
+ setMenuPos({
260
+ top: openUp ? rect.top - 8 : rect.bottom + 6,
261
+ left: rect.left,
262
+ width: Math.max(rect.width, 280),
263
+ openUp
264
+ });
265
+ }
266
+ react.useLayoutEffect(() => {
267
+ if (!open) {
268
+ return;
269
+ }
270
+ updatePosition();
271
+ function onReposition() {
272
+ updatePosition();
273
+ }
274
+ window.addEventListener("resize", onReposition);
275
+ window.addEventListener("scroll", onReposition, true);
276
+ return () => {
277
+ window.removeEventListener("resize", onReposition);
278
+ window.removeEventListener("scroll", onReposition, true);
279
+ };
280
+ }, [open]);
281
+ react.useEffect(() => {
282
+ if (!open) {
283
+ return;
284
+ }
285
+ function onPointerDown(event) {
286
+ const target = event.target;
287
+ if (rootRef.current?.contains(target) || menuRef.current?.contains(target)) {
288
+ return;
289
+ }
290
+ setOpen(false);
291
+ }
292
+ function onKeyDown(event) {
293
+ if (event.key === "Escape") {
294
+ setOpen(false);
295
+ }
296
+ }
297
+ document.addEventListener("mousedown", onPointerDown);
298
+ document.addEventListener("keydown", onKeyDown);
299
+ return () => {
300
+ document.removeEventListener("mousedown", onPointerDown);
301
+ document.removeEventListener("keydown", onKeyDown);
302
+ };
303
+ }, [open]);
304
+ function openPicker() {
305
+ if (locked) {
306
+ return;
307
+ }
308
+ setViewMonth(startOfMonth(selected ?? /* @__PURE__ */ new Date()));
309
+ setOpen(true);
310
+ }
311
+ function choose(date) {
312
+ onChange?.(toIso(date));
313
+ setOpen(false);
314
+ }
315
+ const monthLabel = viewMonth.toLocaleString(void 0, { month: "long", year: "numeric" });
316
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: readOnly ? "date-field read-only" : "date-field", ref: rootRef, children: [
317
+ /* @__PURE__ */ jsxRuntime.jsxs(
318
+ "button",
319
+ {
320
+ type: "button",
321
+ className: open ? "date-field-trigger open" : "date-field-trigger",
322
+ disabled,
323
+ onClick: () => {
324
+ if (locked) {
325
+ return;
326
+ }
327
+ if (open) {
328
+ setOpen(false);
329
+ } else {
330
+ openPicker();
331
+ }
332
+ },
333
+ children: [
334
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: value ? "date-field-value" : "date-field-placeholder", children: value ? formatDisplay(value) : placeholder }),
335
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "date-field-icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
336
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3.5", y: "5", width: "17", height: "15.5", rx: "2", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
337
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3.5 9.5h17M8 3.5v3M16 3.5v3", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" })
338
+ ] })
339
+ ]
340
+ }
341
+ ),
342
+ open && menuPos ? reactDom.createPortal(
343
+ /* @__PURE__ */ jsxRuntime.jsxs(
344
+ "div",
345
+ {
346
+ ref: menuRef,
347
+ className: "date-picker",
348
+ style: {
349
+ top: menuPos.openUp ? void 0 : menuPos.top,
350
+ bottom: menuPos.openUp ? window.innerHeight - menuPos.top : void 0,
351
+ left: menuPos.left,
352
+ width: menuPos.width
353
+ },
354
+ children: [
355
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "date-picker-head", children: [
356
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: monthLabel }),
357
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "date-picker-nav", children: [
358
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", "aria-label": "Previous month", onClick: () => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() - 1, 1)), children: "\u2039" }),
359
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", "aria-label": "Next month", onClick: () => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 1)), children: "\u203A" })
360
+ ] })
361
+ ] }),
362
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "date-picker-weekdays", children: weekdayLabels.map((label) => /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }, label)) }),
363
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "date-picker-grid", children: cells.map((day) => {
364
+ const iso = toIso(day);
365
+ const outside = day.getMonth() !== viewMonth.getMonth();
366
+ const isSelected = value === iso;
367
+ const isToday = today === iso;
368
+ const className = [
369
+ "date-picker-day",
370
+ outside ? "outside" : "",
371
+ isSelected ? "selected" : "",
372
+ isToday ? "today" : ""
373
+ ].filter(Boolean).join(" ");
374
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className, onClick: () => choose(day), children: day.getDate() }, iso + String(outside));
375
+ }) }),
376
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "date-picker-footer", children: [
377
+ /* @__PURE__ */ jsxRuntime.jsx(
378
+ "button",
379
+ {
380
+ type: "button",
381
+ className: "ghost",
382
+ onClick: () => {
383
+ onChange?.("");
384
+ setOpen(false);
385
+ },
386
+ children: "Clear"
387
+ }
388
+ ),
389
+ /* @__PURE__ */ jsxRuntime.jsx(
390
+ "button",
391
+ {
392
+ type: "button",
393
+ className: "ghost",
394
+ onClick: () => {
395
+ const now = /* @__PURE__ */ new Date();
396
+ setViewMonth(startOfMonth(now));
397
+ choose(now);
398
+ },
399
+ children: "Today"
400
+ }
401
+ )
402
+ ] })
403
+ ]
404
+ }
405
+ ),
406
+ document.body
407
+ ) : null
408
+ ] });
409
+ }
410
+ function Dialog({
411
+ title,
412
+ open,
413
+ onClose,
414
+ children,
415
+ wide = true
416
+ }) {
417
+ if (!open) {
418
+ return null;
419
+ }
420
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "dialog-backdrop", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(
421
+ "div",
422
+ {
423
+ className: wide ? "dialog form-dialog" : "dialog",
424
+ role: "dialog",
425
+ "aria-modal": "true",
426
+ "aria-label": title,
427
+ onClick: (event) => event.stopPropagation(),
428
+ children: [
429
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dialog-head", children: [
430
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { children: title }),
431
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", onClick: onClose, children: "Close" })
432
+ ] }),
433
+ children
434
+ ]
435
+ }
436
+ ) });
437
+ }
438
+ var FormDialog = Dialog;
439
+ function useIsClient() {
440
+ return react.useSyncExternalStore(
441
+ () => () => {
442
+ },
443
+ () => true,
444
+ () => false
445
+ );
446
+ }
447
+ function SuccessIcon() {
448
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "snackbar-icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
449
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9", fill: "none", stroke: "currentColor", strokeWidth: "1.8" }),
450
+ /* @__PURE__ */ jsxRuntime.jsx(
451
+ "path",
452
+ {
453
+ d: "M8.2 12.2 10.8 14.8 15.8 9.6",
454
+ fill: "none",
455
+ stroke: "currentColor",
456
+ strokeWidth: "1.8",
457
+ strokeLinecap: "round",
458
+ strokeLinejoin: "round"
459
+ }
460
+ )
461
+ ] });
462
+ }
463
+ function AlertIcon() {
464
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "snackbar-icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
465
+ /* @__PURE__ */ jsxRuntime.jsx(
466
+ "path",
467
+ {
468
+ d: "M12 3.8 3.8 19.2h16.4L12 3.8Z",
469
+ fill: "none",
470
+ stroke: "currentColor",
471
+ strokeWidth: "1.8",
472
+ strokeLinejoin: "round"
473
+ }
474
+ ),
475
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 10v4.2", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
476
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "16.8", r: "1", fill: "currentColor" })
477
+ ] });
478
+ }
479
+ function Snackbar({
480
+ message,
481
+ success,
482
+ onDismiss
483
+ }) {
484
+ const isClient = useIsClient();
485
+ react.useEffect(() => {
486
+ if (!message || !onDismiss) {
487
+ return;
488
+ }
489
+ const timeout = window.setTimeout(onDismiss, success ? 3200 : 4800);
490
+ return () => window.clearTimeout(timeout);
491
+ }, [message, success, onDismiss]);
492
+ if (!isClient || !message) {
493
+ return null;
494
+ }
495
+ return reactDom.createPortal(
496
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "snackbar-host", "aria-live": "polite", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: success ? "snackbar success" : "snackbar", role: "status", children: [
497
+ success ? /* @__PURE__ */ jsxRuntime.jsx(SuccessIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(AlertIcon, {}),
498
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: message }),
499
+ onDismiss ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "snackbar-close", "aria-label": "Dismiss", onClick: onDismiss, children: "\xD7" }) : null
500
+ ] }) }),
501
+ document.body
502
+ );
503
+ }
504
+ var StatusMessage = Snackbar;
505
+ function Topbar({
506
+ title,
507
+ logoSrc,
508
+ logoAlt = "Logo",
509
+ username = "",
510
+ onLogout,
511
+ children
512
+ }) {
513
+ const [menuOpen, setMenuOpen] = react.useState(false);
514
+ const menuRef = react.useRef(null);
515
+ const initial = (username || "U").slice(0, 1).toUpperCase();
516
+ react.useEffect(() => {
517
+ if (!menuOpen) {
518
+ return;
519
+ }
520
+ function onPointerDown(event) {
521
+ if (menuRef.current && !menuRef.current.contains(event.target)) {
522
+ setMenuOpen(false);
523
+ }
524
+ }
525
+ document.addEventListener("mousedown", onPointerDown);
526
+ return () => document.removeEventListener("mousedown", onPointerDown);
527
+ }, [menuOpen]);
528
+ return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "topbar", children: [
529
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "topbar-brand", children: [
530
+ logoSrc ? /* @__PURE__ */ jsxRuntime.jsx(
531
+ "img",
532
+ {
533
+ className: "topbar-logo",
534
+ src: logoSrc,
535
+ alt: logoAlt,
536
+ onError: (event) => {
537
+ event.currentTarget.hidden = true;
538
+ }
539
+ }
540
+ ) : null,
541
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { children: title })
542
+ ] }),
543
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "topbar-actions", ref: menuRef, children: [
544
+ children,
545
+ onLogout ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
546
+ /* @__PURE__ */ jsxRuntime.jsx(
547
+ "button",
548
+ {
549
+ type: "button",
550
+ className: "avatar-button",
551
+ "aria-haspopup": "menu",
552
+ "aria-expanded": menuOpen,
553
+ onClick: () => setMenuOpen((open) => !open),
554
+ title: username || "Account",
555
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "avatar", children: initial })
556
+ }
557
+ ),
558
+ menuOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "avatar-menu", role: "menu", children: [
559
+ username ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "avatar-name", children: username }) : null,
560
+ /* @__PURE__ */ jsxRuntime.jsx(
561
+ Button,
562
+ {
563
+ variant: "ghost",
564
+ role: "menuitem",
565
+ onClick: () => {
566
+ setMenuOpen(false);
567
+ onLogout();
568
+ },
569
+ children: "Logout"
570
+ }
571
+ )
572
+ ] }) : null
573
+ ] }) : null
574
+ ] })
575
+ ] });
576
+ }
577
+ function SideNav({
578
+ items,
579
+ activeId,
580
+ onSelect,
581
+ label = "Sections"
582
+ }) {
583
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "side-nav", "aria-label": label, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
584
+ "button",
585
+ {
586
+ type: "button",
587
+ className: activeId === item.id ? "active" : "",
588
+ onClick: () => onSelect(item.id),
589
+ children: item.label
590
+ },
591
+ item.id
592
+ )) });
593
+ }
594
+ var defaultPageSizes = [
595
+ { value: "15", label: "15" },
596
+ { value: "20", label: "20" },
597
+ { value: "50", label: "50" },
598
+ { value: "100", label: "100" },
599
+ { value: "all", label: "All" }
600
+ ];
601
+ function Pagination({
602
+ page,
603
+ pageCount,
604
+ pageSize,
605
+ onPageChange,
606
+ onPageSizeChange,
607
+ summary,
608
+ pageSizeOptions = defaultPageSizes,
609
+ disabled = false
610
+ }) {
611
+ const showAll = pageSize === "all";
612
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "table-pagination", children: [
613
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "page-size", children: [
614
+ "Rows",
615
+ /* @__PURE__ */ jsxRuntime.jsx(
616
+ Select,
617
+ {
618
+ className: "page-size-select",
619
+ value: pageSize,
620
+ options: pageSizeOptions,
621
+ onChange: onPageSizeChange,
622
+ disabled
623
+ }
624
+ )
625
+ ] }),
626
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "page-summary", children: summary }),
627
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "page-buttons", children: [
628
+ /* @__PURE__ */ jsxRuntime.jsx(
629
+ "button",
630
+ {
631
+ type: "button",
632
+ className: "ghost",
633
+ disabled: disabled || showAll || page <= 1,
634
+ onClick: () => onPageChange(page - 1),
635
+ children: "Previous"
636
+ }
637
+ ),
638
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "page-indicator", children: [
639
+ "Page ",
640
+ showAll ? 1 : page,
641
+ " of ",
642
+ pageCount
643
+ ] }),
644
+ /* @__PURE__ */ jsxRuntime.jsx(
645
+ "button",
646
+ {
647
+ type: "button",
648
+ className: "ghost",
649
+ disabled: disabled || showAll || page >= pageCount,
650
+ onClick: () => onPageChange(page + 1),
651
+ children: "Next"
652
+ }
653
+ )
654
+ ] })
655
+ ] });
656
+ }
657
+ function FormActions({
658
+ pending,
659
+ editing,
660
+ saveLabel,
661
+ updateLabel,
662
+ newLabel,
663
+ onNew,
664
+ saveDisabled = false,
665
+ replaceSaveWhenEditing = false
666
+ }) {
667
+ if (editing && replaceSaveWhenEditing) {
668
+ return null;
669
+ }
670
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "actions", children: [
671
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", disabled: pending || saveDisabled, children: editing && updateLabel ? updateLabel : saveLabel }),
672
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost", onClick: onNew, children: newLabel })
673
+ ] });
674
+ }
675
+ function AppShell({
676
+ title,
677
+ logoSrc,
678
+ logoAlt,
679
+ username,
680
+ onLogout,
681
+ navItems,
682
+ activeNavId,
683
+ onNavSelect,
684
+ navLabel = "Sections",
685
+ showBottomNav = true,
686
+ topbarActions,
687
+ children,
688
+ screenClassName = ""
689
+ }) {
690
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aksui-root app-shell", children: [
691
+ /* @__PURE__ */ jsxRuntime.jsx(Topbar, { title, logoSrc, logoAlt, username, onLogout, children: topbarActions }),
692
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "app-body", children: [
693
+ /* @__PURE__ */ jsxRuntime.jsx(SideNav, { items: navItems, activeId: activeNavId, onSelect: onNavSelect, label: navLabel }),
694
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["screen", screenClassName].filter(Boolean).join(" "), children })
695
+ ] }),
696
+ showBottomNav ? /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "bottom-nav", "aria-label": navLabel, children: navItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
697
+ "button",
698
+ {
699
+ type: "button",
700
+ className: activeNavId === item.id ? "active" : "",
701
+ onClick: () => onNavSelect(item.id),
702
+ children: item.short ?? item.label
703
+ },
704
+ item.id
705
+ )) }) : null
706
+ ] });
707
+ }
708
+ function useIsClient2() {
709
+ return react.useSyncExternalStore(
710
+ () => () => {
711
+ },
712
+ () => true,
713
+ () => false
714
+ );
715
+ }
716
+ function compareColumnValues(column, left, right) {
717
+ const leftRaw = column.display ? column.display(left) : column.value(left);
718
+ const rightRaw = column.display ? column.display(right) : column.value(right);
719
+ if (leftRaw === null || leftRaw === void 0 || leftRaw === "") {
720
+ return rightRaw === null || rightRaw === void 0 || rightRaw === "" ? 0 : 1;
721
+ }
722
+ if (rightRaw === null || rightRaw === void 0 || rightRaw === "") {
723
+ return -1;
724
+ }
725
+ if (typeof leftRaw === "number" && typeof rightRaw === "number") {
726
+ return leftRaw - rightRaw;
727
+ }
728
+ const leftText = String(leftRaw);
729
+ const rightText = String(rightRaw);
730
+ const leftNumber = Number(leftText);
731
+ const rightNumber = Number(rightText);
732
+ if (leftText.trim() !== "" && rightText.trim() !== "" && Number.isFinite(leftNumber) && Number.isFinite(rightNumber) && /^-?\d+(\.\d+)?$/.test(leftText.trim()) && /^-?\d+(\.\d+)?$/.test(rightText.trim())) {
733
+ return leftNumber - rightNumber;
734
+ }
735
+ return leftText.localeCompare(rightText, void 0, { sensitivity: "base", numeric: true });
736
+ }
737
+ function PlusIcon() {
738
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 4v12M4 10h12", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) });
739
+ }
740
+ function FilterIcon() {
741
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 5h14M5.5 10h9M8 15h4", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }) });
742
+ }
743
+ function ResetIcon() {
744
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
745
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.5 8.2A6 6 0 1 1 4.8 13", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
746
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.5 4.2v4h4", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" })
747
+ ] });
748
+ }
749
+ function ChevronIcon({ open }) {
750
+ return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: open ? "side-rail-chevron open" : "side-rail-chevron", viewBox: "0 0 20 20", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 4.5 13.5 10 8 15.5", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) });
751
+ }
752
+ function PreviewIcon() {
753
+ return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 20 20", "aria-hidden": "true", children: [
754
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2.8 10S5.5 4.8 10 4.8 17.2 10 17.2 10 14.5 15.2 10 15.2 2.8 10 2.8 10Z", fill: "none", stroke: "currentColor", strokeWidth: "1.6" }),
755
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "2.4", fill: "none", stroke: "currentColor", strokeWidth: "1.6" })
756
+ ] });
757
+ }
758
+ function DetailList({ lines }) {
759
+ return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: "record-detail-list", children: lines.map((line) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "record-detail-row", children: [
760
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { children: line.label }),
761
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { children: line.value })
762
+ ] }, line.label)) });
763
+ }
764
+ function RecordWorkspace({
765
+ title,
766
+ columns,
767
+ items,
768
+ rowKey,
769
+ empty,
770
+ onAdd,
771
+ addLabel = "Add",
772
+ canAdd = true,
773
+ onView,
774
+ onUpdate,
775
+ onDelete,
776
+ canUpdate,
777
+ canDelete,
778
+ toolbar,
779
+ form
780
+ }) {
781
+ const filterableColumns = columns.filter((column) => column.filterable !== false);
782
+ const [filters, setFilters] = react.useState({});
783
+ const [sort, setSort] = react.useState(null);
784
+ const [sideOpen, setSideOpen] = react.useState(false);
785
+ const [previewEnabled, setPreviewEnabled] = react.useState(false);
786
+ const [previewKey, setPreviewKey] = react.useState(null);
787
+ const [tooltip, setTooltip] = react.useState(null);
788
+ const [pageSize, setPageSize] = react.useState("15");
789
+ const [page, setPage] = react.useState(1);
790
+ const isClient = useIsClient2();
791
+ const filtered = react.useMemo(() => {
792
+ const activeFilters = columns.filter((column) => column.filterable !== false);
793
+ return items.filter(
794
+ (item) => activeFilters.every((column) => {
795
+ const query = (filters[column.key] ?? "").trim();
796
+ if (!query) {
797
+ return true;
798
+ }
799
+ const raw = column.value(item);
800
+ const text = raw === null || raw === void 0 ? "" : String(raw);
801
+ if (column.filterOptions) {
802
+ return text === query;
803
+ }
804
+ return text.toLowerCase().includes(query.toLowerCase());
805
+ })
806
+ );
807
+ }, [items, filters, columns]);
808
+ const sorted = react.useMemo(() => {
809
+ if (!sort) {
810
+ return filtered;
811
+ }
812
+ const column = columns.find((entry) => entry.key === sort.key);
813
+ if (!column || column.sortable === false) {
814
+ return filtered;
815
+ }
816
+ const direction = sort.direction === "asc" ? 1 : -1;
817
+ return [...filtered].sort((left, right) => compareColumnValues(column, left, right) * direction);
818
+ }, [filtered, sort, columns]);
819
+ const activeFilterCount = react.useMemo(
820
+ () => filterableColumns.reduce((count, column) => count + ((filters[column.key] ?? "").trim() ? 1 : 0), 0),
821
+ [filterableColumns, filters]
822
+ );
823
+ const showAll = pageSize === "all";
824
+ const numericPageSize = showAll ? Math.max(sorted.length, 1) : Number(pageSize);
825
+ const pageCount = showAll ? 1 : Math.max(1, Math.ceil(sorted.length / numericPageSize));
826
+ const currentPage = Math.min(page, pageCount);
827
+ const start = showAll ? 0 : (currentPage - 1) * numericPageSize;
828
+ const pageItems = showAll ? sorted : sorted.slice(start, start + numericPageSize);
829
+ const showAdd = canAdd && Boolean(onAdd);
830
+ const showFilters = filterableColumns.length > 0;
831
+ const previewItem = previewKey === null ? null : sorted.find((item) => rowKey(item) === previewKey) ?? null;
832
+ function cellText(column, item) {
833
+ const raw = column.display ? column.display(item) : column.value(item);
834
+ return raw === null || raw === void 0 || raw === "" ? "\u2014" : String(raw);
835
+ }
836
+ function detailLines(item) {
837
+ return columns.map((column) => ({
838
+ label: column.header,
839
+ value: cellText(column, item)
840
+ }));
841
+ }
842
+ const previewTitle = previewItem && columns[0] ? cellText(columns[0], previewItem) : null;
843
+ function changeFilter(key, value) {
844
+ setFilters((current) => ({ ...current, [key]: value }));
845
+ setPage(1);
846
+ }
847
+ function clearFilters() {
848
+ setFilters({});
849
+ setPage(1);
850
+ }
851
+ function toggleSort(column) {
852
+ if (column.sortable === false) {
853
+ return;
854
+ }
855
+ setSort((current) => {
856
+ if (!current || current.key !== column.key) {
857
+ return { key: column.key, direction: "asc" };
858
+ }
859
+ if (current.direction === "asc") {
860
+ return { key: column.key, direction: "desc" };
861
+ }
862
+ return null;
863
+ });
864
+ setPage(1);
865
+ }
866
+ function setPreviewEnabledValue(enabled) {
867
+ setPreviewEnabled(enabled);
868
+ setTooltip(null);
869
+ if (!enabled) {
870
+ setPreviewKey(null);
871
+ }
872
+ }
873
+ function focusRecord(item) {
874
+ if (previewEnabled) {
875
+ setPreviewKey(rowKey(item));
876
+ }
877
+ }
878
+ function showTooltip(item, event) {
879
+ const padding = 16;
880
+ const width = 280;
881
+ const x = Math.min(event.clientX + 14, window.innerWidth - width - padding);
882
+ const y = Math.min(event.clientY + 14, window.innerHeight - padding - 24);
883
+ setTooltip({ x, y, lines: detailLines(item) });
884
+ }
885
+ const summary = sorted.length === 0 ? "0 records" : showAll ? `1\u2013${sorted.length} of ${sorted.length}` : `${start + 1}\u2013${Math.min(start + numericPageSize, sorted.length)} of ${sorted.length}`;
886
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "list-workspace", "aria-label": title, children: [
887
+ /* @__PURE__ */ jsxRuntime.jsxs(
888
+ "div",
889
+ {
890
+ className: ["list-body", sideOpen ? "side-open" : "", previewEnabled ? "preview-open" : ""].filter(Boolean).join(" "),
891
+ children: [
892
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "list-main", children: /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "table-card", children: [
893
+ toolbar ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-card-bar", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-card-context", children: toolbar }) }) : null,
894
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-wrap", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "data-table", children: [
895
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
896
+ columns.map((column) => {
897
+ const sortable = column.sortable !== false;
898
+ const active = sort?.key === column.key ? sort.direction : null;
899
+ return /* @__PURE__ */ jsxRuntime.jsx(
900
+ "th",
901
+ {
902
+ "aria-sort": active === "asc" ? "ascending" : active === "desc" ? "descending" : "none",
903
+ children: sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
904
+ "button",
905
+ {
906
+ type: "button",
907
+ className: active ? `sort-header active ${active}` : "sort-header",
908
+ onClick: () => toggleSort(column),
909
+ children: [
910
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: column.header }),
911
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sort-indicator", "aria-hidden": "true", children: active === "asc" ? "\u25B2" : active === "desc" ? "\u25BC" : "\u2195" })
912
+ ]
913
+ }
914
+ ) : column.header
915
+ },
916
+ column.key
917
+ );
918
+ }),
919
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "actions-col", children: "Actions" })
920
+ ] }) }),
921
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: pageItems.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx("td", { colSpan: columns.length + 1, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "hint table-empty", children: items.length === 0 ? empty : "No records match the current filters." }) }) }) : pageItems.map((item) => {
922
+ const key = rowKey(item);
923
+ const updateAllowed = canUpdate ? canUpdate(item) : Boolean(onUpdate);
924
+ const deleteAllowed = canDelete ? canDelete(item) : Boolean(onDelete);
925
+ const selected = previewEnabled && previewKey === key;
926
+ return /* @__PURE__ */ jsxRuntime.jsxs(
927
+ "tr",
928
+ {
929
+ className: selected ? "data-row selected" : "data-row",
930
+ onMouseEnter: (event) => {
931
+ if (!previewEnabled) {
932
+ showTooltip(item, event);
933
+ }
934
+ focusRecord(item);
935
+ },
936
+ onMouseMove: (event) => {
937
+ if (!previewEnabled) {
938
+ showTooltip(item, event);
939
+ }
940
+ },
941
+ onMouseLeave: () => setTooltip(null),
942
+ onClick: () => focusRecord(item),
943
+ children: [
944
+ columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx("td", { children: cellText(column, item) }, column.key)),
945
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "actions-col", onClick: (event) => event.stopPropagation(), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "row-actions", children: [
946
+ onView ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost row-action", onClick: () => onView(item), children: "View" }) : null,
947
+ onUpdate ? /* @__PURE__ */ jsxRuntime.jsx(
948
+ "button",
949
+ {
950
+ type: "button",
951
+ className: "ghost row-action",
952
+ disabled: !updateAllowed,
953
+ title: updateAllowed ? "Update" : "Update is not available",
954
+ onClick: () => onUpdate(item),
955
+ children: "Update"
956
+ }
957
+ ) : null,
958
+ onDelete ? /* @__PURE__ */ jsxRuntime.jsx(
959
+ "button",
960
+ {
961
+ type: "button",
962
+ className: "ghost row-action danger",
963
+ disabled: !deleteAllowed,
964
+ title: deleteAllowed ? "Delete" : "Delete is not available",
965
+ onClick: () => onDelete(item),
966
+ children: "Delete"
967
+ }
968
+ ) : null
969
+ ] }) })
970
+ ]
971
+ },
972
+ key
973
+ );
974
+ }) })
975
+ ] }) }),
976
+ /* @__PURE__ */ jsxRuntime.jsx(
977
+ Pagination,
978
+ {
979
+ page: currentPage,
980
+ pageCount,
981
+ pageSize,
982
+ onPageChange: setPage,
983
+ onPageSizeChange: (value) => {
984
+ setPageSize(value);
985
+ setPage(1);
986
+ },
987
+ summary
988
+ }
989
+ )
990
+ ] }) }),
991
+ previewEnabled ? /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "preview-panel", "aria-label": "Record preview", children: [
992
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "preview-panel-head", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
993
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "preview-kicker", children: "Preview" }),
994
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: previewTitle ?? "No record selected" })
995
+ ] }) }),
996
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "preview-panel-body", children: previewItem ? /* @__PURE__ */ jsxRuntime.jsx(DetailList, { lines: detailLines(previewItem) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "preview-empty", children: "Hover or click a row to preview its details here." }) })
997
+ ] }) : null,
998
+ /* @__PURE__ */ jsxRuntime.jsxs("aside", { className: sideOpen ? "side-rail open" : "side-rail", "aria-label": "Actions and filters", children: [
999
+ /* @__PURE__ */ jsxRuntime.jsxs(
1000
+ "button",
1001
+ {
1002
+ type: "button",
1003
+ className: "ghost side-rail-toggle",
1004
+ "aria-expanded": sideOpen,
1005
+ title: sideOpen ? "Collapse" : "Expand",
1006
+ onClick: () => setSideOpen((open) => !open),
1007
+ children: [
1008
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronIcon, { open: sideOpen }),
1009
+ sideOpen ? /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Collapse" }) : null
1010
+ ]
1011
+ }
1012
+ ),
1013
+ sideOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-body", children: [
1014
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "preview-check", children: [
1015
+ /* @__PURE__ */ jsxRuntime.jsx(
1016
+ "input",
1017
+ {
1018
+ type: "checkbox",
1019
+ checked: previewEnabled,
1020
+ onChange: (event) => setPreviewEnabledValue(event.target.checked),
1021
+ "aria-label": "Preview"
1022
+ }
1023
+ ),
1024
+ /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, {}),
1025
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "Preview" })
1026
+ ] }),
1027
+ showAdd ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "side-rail-add", onClick: onAdd, children: [
1028
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}),
1029
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: addLabel })
1030
+ ] }) : null,
1031
+ showFilters ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-filters", children: [
1032
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "filter-panel-head", children: [
1033
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Filters" }),
1034
+ /* @__PURE__ */ jsxRuntime.jsxs(
1035
+ "button",
1036
+ {
1037
+ type: "button",
1038
+ className: "ghost filter-clear",
1039
+ title: "Reset filters",
1040
+ "aria-label": "Reset filters",
1041
+ disabled: activeFilterCount === 0,
1042
+ onClick: clearFilters,
1043
+ children: [
1044
+ /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, {}),
1045
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Reset" })
1046
+ ]
1047
+ }
1048
+ )
1049
+ ] }),
1050
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "filter-panel-stack", children: filterableColumns.map((column) => /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
1051
+ column.header,
1052
+ column.filterOptions ? /* @__PURE__ */ jsxRuntime.jsx(
1053
+ Select,
1054
+ {
1055
+ value: filters[column.key] ?? "",
1056
+ options: [{ value: "", label: column.filterPlaceholder ?? "All" }, ...column.filterOptions],
1057
+ onChange: (value) => changeFilter(column.key, value),
1058
+ placeholder: column.filterPlaceholder ?? "All"
1059
+ }
1060
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1061
+ "input",
1062
+ {
1063
+ value: filters[column.key] ?? "",
1064
+ onChange: (event) => changeFilter(column.key, event.target.value),
1065
+ placeholder: `Filter ${column.header.toLowerCase()}`
1066
+ }
1067
+ )
1068
+ ] }, column.key)) })
1069
+ ] }) : null
1070
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "side-rail-icons", children: [
1071
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "side-rail-icon preview-check-icon", title: "Preview", children: [
1072
+ /* @__PURE__ */ jsxRuntime.jsx(
1073
+ "input",
1074
+ {
1075
+ type: "checkbox",
1076
+ checked: previewEnabled,
1077
+ onChange: (event) => setPreviewEnabledValue(event.target.checked),
1078
+ "aria-label": "Preview"
1079
+ }
1080
+ ),
1081
+ /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, {})
1082
+ ] }),
1083
+ showAdd ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "ghost side-rail-icon", title: addLabel, "aria-label": addLabel, onClick: onAdd, children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, {}) }) : null,
1084
+ showFilters ? /* @__PURE__ */ jsxRuntime.jsxs(
1085
+ "button",
1086
+ {
1087
+ type: "button",
1088
+ className: "ghost side-rail-icon",
1089
+ title: "Show filters",
1090
+ "aria-label": "Show filters",
1091
+ onClick: () => setSideOpen(true),
1092
+ children: [
1093
+ /* @__PURE__ */ jsxRuntime.jsx(FilterIcon, {}),
1094
+ activeFilterCount > 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "filter-badge", children: activeFilterCount }) : null
1095
+ ]
1096
+ }
1097
+ ) : null,
1098
+ showFilters ? /* @__PURE__ */ jsxRuntime.jsx(
1099
+ "button",
1100
+ {
1101
+ type: "button",
1102
+ className: "ghost side-rail-icon",
1103
+ title: "Reset filters",
1104
+ "aria-label": "Reset filters",
1105
+ disabled: activeFilterCount === 0,
1106
+ onClick: clearFilters,
1107
+ children: /* @__PURE__ */ jsxRuntime.jsx(ResetIcon, {})
1108
+ }
1109
+ ) : null
1110
+ ] })
1111
+ ] })
1112
+ ]
1113
+ }
1114
+ ),
1115
+ form,
1116
+ isClient && tooltip && !previewEnabled ? reactDom.createPortal(
1117
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "record-tooltip", style: { left: tooltip.x, top: tooltip.y }, role: "tooltip", children: [
1118
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "record-tooltip-title", children: title }),
1119
+ /* @__PURE__ */ jsxRuntime.jsx(DetailList, { lines: tooltip.lines })
1120
+ ] }),
1121
+ document.body
1122
+ ) : null
1123
+ ] });
1124
+ }
1125
+ var RecordTable = RecordWorkspace;
1126
+
1127
+ exports.AppSelect = AppSelect;
1128
+ exports.AppShell = AppShell;
1129
+ exports.Button = Button;
1130
+ exports.DateField = DateField;
1131
+ exports.Dialog = Dialog;
1132
+ exports.FormActions = FormActions;
1133
+ exports.FormDialog = FormDialog;
1134
+ exports.Pagination = Pagination;
1135
+ exports.RecordTable = RecordTable;
1136
+ exports.RecordWorkspace = RecordWorkspace;
1137
+ exports.Select = Select;
1138
+ exports.SideNav = SideNav;
1139
+ exports.Snackbar = Snackbar;
1140
+ exports.StatusMessage = StatusMessage;
1141
+ exports.Topbar = Topbar;
1142
+ exports.aksuiThemeVersion = aksuiThemeVersion;
1143
+ exports.aksuiTokens = aksuiTokens;
1144
+ //# sourceMappingURL=index.cjs.map
1145
+ //# sourceMappingURL=index.cjs.map