@warkypublic/svelix 0.1.46 → 0.2.1

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 (129) hide show
  1. package/README.md +93 -33
  2. package/dist/components/BetterMenu/BetterMenu.svelte +21 -37
  3. package/dist/components/BetterMenu/BetterMenuAsyncButton.svelte +21 -31
  4. package/dist/components/BetterMenu/BetterMenuPreview.svelte +27 -29
  5. package/dist/components/BetterMenu/MenuRenderer.svelte +40 -51
  6. package/dist/components/Boxer/Boxer.svelte +492 -602
  7. package/dist/components/Boxer/BoxerTarget.svelte +6 -46
  8. package/dist/components/Boxer/BoxerTarget.svelte.d.ts +1 -0
  9. package/dist/components/Boxer/types.d.ts +0 -1
  10. package/dist/components/Button.svelte +19 -43
  11. package/dist/components/ButtonPreview.svelte +2 -11
  12. package/dist/components/CardGrid/CardGrid.svelte +489 -614
  13. package/dist/components/CardGrid/CardGrid.svelte.d.ts +4 -0
  14. package/dist/components/CardGrid/CardGridFilterPanel.svelte +111 -90
  15. package/dist/components/CardGrid/DefaultCard.svelte +86 -97
  16. package/dist/components/CardGrid/DefaultCard.svelte.d.ts +1 -0
  17. package/dist/components/CardGrid/ImageCardStory.svelte +87 -36
  18. package/dist/components/CardGrid/cardGrid.d.ts +24 -0
  19. package/dist/components/CardGrid/cardGrid.js +20 -0
  20. package/dist/components/ContentEditor/CollaboraInsertTextDemo.svelte +5 -10
  21. package/dist/components/ContentEditor/ContentEditor.svelte +24 -50
  22. package/dist/components/ContentEditor/subcomponents/AudioPlayer.svelte +17 -17
  23. package/dist/components/ContentEditor/subcomponents/CollaboraEditor.svelte +244 -309
  24. package/dist/components/ContentEditor/subcomponents/EmailViewer.svelte +2 -3
  25. package/dist/components/ContentEditor/subcomponents/ImageViewer.svelte +14 -15
  26. package/dist/components/ContentEditor/subcomponents/MarkdownViewer.svelte +74 -90
  27. package/dist/components/ContentEditor/subcomponents/MonacoEditor.svelte +75 -103
  28. package/dist/components/ContentEditor/subcomponents/Office365Editor.svelte +234 -297
  29. package/dist/components/ContentEditor/subcomponents/PdfViewer.svelte +14 -20
  30. package/dist/components/ContentEditor/subcomponents/TextEditor.svelte +122 -150
  31. package/dist/components/ContentEditor/subcomponents/UnknownFile.svelte +105 -126
  32. package/dist/components/ContentEditor/subcomponents/VideoPlayer.svelte +17 -17
  33. package/dist/components/ContentEditor/subcomponents/ZipViewer.svelte +2 -3
  34. package/dist/components/ErrorBoundary/ErrorBoundary.svelte +41 -58
  35. package/dist/components/ErrorBoundary/ErrorBoundaryPreview.svelte +8 -16
  36. package/dist/components/Former/Former.svelte +306 -424
  37. package/dist/components/Former/FormerButtonArea.svelte +17 -68
  38. package/dist/components/Former/FormerDrawer.svelte +16 -80
  39. package/dist/components/Former/FormerDrawerPreview.svelte +99 -89
  40. package/dist/components/Former/FormerModal.svelte +16 -74
  41. package/dist/components/Former/FormerModalPreview.svelte +99 -89
  42. package/dist/components/Former/FormerPreview.svelte +76 -78
  43. package/dist/components/Former/FormerRestApiPreview.svelte +55 -48
  44. package/dist/components/Former/formerOverlayHelpers.svelte.d.ts +11 -0
  45. package/dist/components/Former/formerOverlayHelpers.svelte.js +38 -0
  46. package/dist/components/Former/index.d.ts +1 -0
  47. package/dist/components/Former/index.js +1 -0
  48. package/dist/components/FormerControllers/ButtonCtrl.svelte +13 -49
  49. package/dist/components/FormerControllers/CtrlFieldShell.svelte +15 -0
  50. package/dist/components/FormerControllers/CtrlFieldShell.svelte.d.ts +12 -0
  51. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrl.svelte +285 -457
  52. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlCalendar.svelte +95 -136
  53. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlPickerPanel.svelte +3 -62
  54. package/dist/components/FormerControllers/DateTimeCtrl/DateTimeCtrlTimeFields.svelte +143 -217
  55. package/dist/components/FormerControllers/IconButtonCtrl.svelte +13 -47
  56. package/dist/components/FormerControllers/InlineWrapper.svelte +12 -41
  57. package/dist/components/FormerControllers/InlineWrapperPreview.svelte +4 -26
  58. package/dist/components/FormerControllers/NativeSelectCtrl.svelte +7 -39
  59. package/dist/components/FormerControllers/NumberInputCtrl.svelte +21 -43
  60. package/dist/components/FormerControllers/PasswordInputCtrl.svelte +8 -33
  61. package/dist/components/FormerControllers/SwitchCtrl.svelte +4 -20
  62. package/dist/components/FormerControllers/TextAreaCtrl.svelte +7 -34
  63. package/dist/components/FormerControllers/TextInputCtrl.svelte +7 -34
  64. package/dist/components/FormerControllers/ctrlLoading.svelte.d.ts +8 -0
  65. package/dist/components/FormerControllers/ctrlLoading.svelte.js +43 -0
  66. package/dist/components/FormerControllers/index.d.ts +2 -0
  67. package/dist/components/FormerControllers/index.js +2 -0
  68. package/dist/components/FormerControllers/utils.d.ts +1 -0
  69. package/dist/components/FormerControllers/utils.js +3 -0
  70. package/dist/components/GlobalStateStore/GlobalStateStoreProvider.svelte +73 -120
  71. package/dist/components/Gridler/components/Gridler.svelte +344 -442
  72. package/dist/components/Gridler/components/GridlerCanvas.svelte +720 -1115
  73. package/dist/components/Gridler/components/GridlerEditor.svelte +2 -15
  74. package/dist/components/Gridler/components/GridlerFull.svelte +521 -841
  75. package/dist/components/Gridler/components/GridlerFull.svelte.d.ts +1 -1
  76. package/dist/components/Gridler/components/GridlerFullWithFormerPreview.svelte +194 -147
  77. package/dist/components/Gridler/components/GridlerSearch.svelte +7 -16
  78. package/dist/components/Gridler/components/GridlerSearchToggle.svelte +7 -19
  79. package/dist/components/Gridler/types.d.ts +1 -1
  80. package/dist/components/Gridler/utils/serverPaging.d.ts +1 -0
  81. package/dist/components/Gridler/utils/serverPaging.js +7 -0
  82. package/dist/components/Icons/IconAdd.svelte +1 -3
  83. package/dist/components/Icons/IconAlertCircle.svelte +1 -3
  84. package/dist/components/Icons/IconAlertTriangle.svelte +1 -3
  85. package/dist/components/Icons/IconCamera.svelte +1 -3
  86. package/dist/components/Icons/IconClose.svelte +1 -3
  87. package/dist/components/Icons/IconEdit.svelte +1 -3
  88. package/dist/components/Icons/IconFilter.svelte +1 -3
  89. package/dist/components/Icons/IconSearch.svelte +1 -3
  90. package/dist/components/Icons/IconSort.svelte +1 -3
  91. package/dist/components/Icons/IconTrash.svelte +1 -3
  92. package/dist/components/Portal/Portal.svelte +14 -38
  93. package/dist/components/Screenshot/Screenshot.svelte +7 -13
  94. package/dist/components/Svark/Svark.svelte +680 -852
  95. package/dist/components/Svark/SvarkContextMenu.svelte +44 -63
  96. package/dist/components/Svark/SvarkInfiniteLoader.svelte +2 -6
  97. package/dist/components/Svark/SvarkPager.svelte +2 -28
  98. package/dist/components/Svark/SvarkSelectionDemo.svelte +4 -8
  99. package/dist/components/Svark/SvarkTopBar.svelte +9 -74
  100. package/dist/components/SvarkGrid/SvarkGrid.svelte +877 -1123
  101. package/dist/components/SvarkGrid/components/SvarkColumnFilterForm.svelte +45 -58
  102. package/dist/components/SvarkGrid/components/SvarkContextMenu.svelte +44 -63
  103. package/dist/components/SvarkGrid/components/SvarkHeaderFilterCell.svelte +41 -75
  104. package/dist/components/SvarkGrid/components/SvarkInfiniteLoader.svelte +2 -6
  105. package/dist/components/SvarkGrid/components/SvarkPager.svelte +2 -28
  106. package/dist/components/SvarkGrid/components/SvarkSearchPopover.svelte +8 -16
  107. package/dist/components/SvarkGrid/components/SvarkTopBar.svelte +6 -62
  108. package/dist/components/SvarkGrid/internal/SvarkGridView.svelte +345 -507
  109. package/dist/components/VTree/VTree.svelte +454 -431
  110. package/dist/components/VTree/VTree.utils.d.ts +23 -0
  111. package/dist/components/VTree/VTree.utils.js +73 -0
  112. package/dist/components/VTree/VTreeContextMenu.svelte +21 -33
  113. package/dist/components/VTree/VTreeControlledSelectionDemo.svelte +20 -0
  114. package/dist/components/VTree/VTreeControlledSelectionDemo.svelte.d.ts +18 -0
  115. package/dist/components/VTree/VTreeCustomizationDemo.svelte +23 -0
  116. package/dist/components/VTree/VTreeCustomizationDemo.svelte.d.ts +18 -0
  117. package/dist/components/VTree/VTreeEventsDemo.svelte +48 -58
  118. package/dist/components/VTree/VTreeInteractionDemo.svelte +29 -0
  119. package/dist/components/VTree/VTreeInteractionDemo.svelte.d.ts +18 -0
  120. package/dist/components/VTree/VTreeMultiSelectDemo.svelte +27 -0
  121. package/dist/components/VTree/VTreeMultiSelectDemo.svelte.d.ts +18 -0
  122. package/dist/components/VTree/VTreeRow.svelte +77 -115
  123. package/dist/components/VTree/VTreeRow.svelte.d.ts +34 -18
  124. package/dist/components/VTree/VTreeSearch.svelte +6 -13
  125. package/dist/components/VTree/VTreeVirtualViewport.svelte +54 -143
  126. package/dist/components/VTree/VTreeVirtualViewport.svelte.d.ts +35 -18
  127. package/dist/components/VTree/types.d.ts +39 -1
  128. package/llm/COMPONENT_GUIDE.md +25 -0
  129. package/package.json +51 -50
@@ -1,71 +1,20 @@
1
- <script lang="ts">
2
- import type { FormRequestType } from "./types";
3
-
4
- export interface Props {
5
- closeButtonTitle?: string;
6
- deleteConfirmed?: boolean;
7
- dirty?: boolean;
8
- keepOpen?: boolean;
9
- onClose?: () => void;
10
- onSave?: () => Promise<void>;
11
- onToggleKeepOpen?: (checked: boolean) => void;
12
- request?: FormRequestType;
13
- saveButtonTitle?: string;
14
- showKeepOpenSwitch?: boolean;
15
- }
16
-
17
- const {
18
- closeButtonTitle = "Close",
19
- deleteConfirmed,
20
- dirty,
21
- keepOpen,
22
- onClose,
23
- onSave,
24
- onToggleKeepOpen,
25
- request,
26
- saveButtonTitle,
27
- showKeepOpenSwitch,
28
- }: Props = $props();
29
-
30
- const effectiveSaveTitle = $derived(
31
- saveButtonTitle ?? (request === "delete" ? "Delete" : "Save"),
32
- );
33
-
34
- const saveIcon = $derived(request === "delete" ? "🗑" : "💾");
35
-
36
- const disabledSave = $derived(
37
- ["select", "view"].includes(request ?? "") ||
38
- (["update"].includes(request ?? "") && !dirty) ||
39
- (request === "delete" && !deleteConfirmed),
40
- );
41
-
42
- const saveTooltip = $derived(
43
- disabledSave
44
- ? request === "delete"
45
- ? "Confirm deletion below before proceeding."
46
- : "Cannot save in view or select mode, or no changes made."
47
- : request === "delete"
48
- ? "Permanently delete this record"
49
- : "Save the current record",
50
- );
51
-
52
- const saveBtnClass = $derived(
53
- request === "delete"
54
- ? "preset-filled-error-token"
55
- : "preset-filled-primary-500",
56
- );
57
-
58
- let saving = $state(false);
59
-
60
- async function handleSave() {
61
- if (!onSave) return;
62
- saving = true;
63
- try {
64
- await onSave();
65
- } finally {
66
- saving = false;
67
- }
68
- }
1
+ <script lang="ts">const { closeButtonTitle = "Close", deleteConfirmed, dirty, keepOpen, onClose, onSave, onToggleKeepOpen, request, saveButtonTitle, showKeepOpenSwitch } = $props();
2
+ const effectiveSaveTitle = $derived(saveButtonTitle ?? (request === "delete" ? "Delete" : "Save"));
3
+ const saveIcon = $derived(request === "delete" ? "🗑" : "💾");
4
+ const disabledSave = $derived(["select", "view"].includes(request ?? "") || ["update"].includes(request ?? "") && !dirty || request === "delete" && !deleteConfirmed);
5
+ const saveTooltip = $derived(disabledSave ? request === "delete" ? "Confirm deletion below before proceeding." : "Cannot save in view or select mode, or no changes made." : request === "delete" ? "Permanently delete this record" : "Save the current record");
6
+ const saveBtnClass = $derived(request === "delete" ? "preset-filled-error-token" : "preset-filled-primary-500");
7
+ let saving = $state(false);
8
+ async function handleSave() {
9
+ if (!onSave) return;
10
+ saving = true;
11
+ try {
12
+ await onSave();
13
+ } finally {
14
+ saving = false;
15
+ }
16
+ }
17
+ export {};
69
18
  </script>
70
19
 
71
20
  <div
@@ -1,81 +1,17 @@
1
- <script lang="ts">
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- import { Dialog, Portal } from "@skeletonlabs/skeleton-svelte";
4
- import { registerOverlay } from "../OverlayStack";
5
- import Former from "./Former.svelte";
6
- import type { FormerProps, FormRequestType } from "./types";
7
-
8
- export interface Props extends FormerProps {
9
- /**
10
- * Override the auto-generated drawer title.
11
- * When omitted the title is derived from the request type and the unique key value:
12
- * insert → "New Record"
13
- * update → "Edit Record {key}"
14
- * delete → "Delete Record {key}"
15
- */
16
- title?: string;
17
- /**
18
- * Width of the drawer panel.
19
- * @default '32rem'
20
- */
21
- width?: string;
22
- }
23
-
24
- let {
25
- afterGet,
26
- afterSave,
27
- beforeSave,
28
- children,
29
- id,
30
- keepOpen = $bindable(false),
31
- layout,
32
- onAPICall,
33
- onChange,
34
- onClose,
35
- onConfirmDelete,
36
- onError,
37
- onOpen,
38
- opened = $bindable(false),
39
- primeData,
40
- request = $bindable<FormRequestType>("insert"),
41
- title,
42
- uniqueKeyField = "id",
43
- values = $bindable<any>(undefined),
44
- width = "32rem",
45
- }: Props = $props();
46
-
47
- const autoTitle = $derived(
48
- title ??
49
- (request === "delete"
50
- ? `Delete Record${(values as any)?.[uniqueKeyField] ? ` — ${(values as any)[uniqueKeyField]}` : ""}`
51
- : request === "insert"
52
- ? "New Record"
53
- : `Edit Record${(values as any)?.[uniqueKeyField] ? ` — ${(values as any)[uniqueKeyField]}` : ""}`),
54
- );
55
-
56
- const animBackdrop =
57
- "transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100";
58
- const animContent =
59
- "transition transition-discrete opacity-0 translate-x-full starting:data-[state=open]:opacity-0 starting:data-[state=open]:translate-x-full data-[state=open]:opacity-100 data-[state=open]:translate-x-0";
60
-
61
- let backdropZ = $state(1000);
62
- let contentZ = $state(1010);
63
-
64
- $effect(() => {
65
- if (!opened) {
66
- return;
67
- }
68
-
69
- const overlay = registerOverlay({ kind: "drawer", mount: "portal" });
70
- backdropZ = overlay.layer.backdrop;
71
- contentZ = overlay.layer.content;
72
-
73
- return () => {
74
- overlay.unregister();
75
- backdropZ = 1000;
76
- contentZ = 1010;
77
- };
78
- });
1
+ <script lang="ts">/* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Dialog, Portal } from "@skeletonlabs/skeleton-svelte";
3
+ import Former from "./Former.svelte";
4
+ import { createOverlayZIndex, deriveAutoTitle } from "./formerOverlayHelpers.svelte";
5
+ let { afterGet, afterSave, beforeSave, children, id, keepOpen = $bindable(false), layout, onAPICall, onChange, onClose, onConfirmDelete, onError, onOpen, opened = $bindable(false), primeData, request = $bindable("insert"), title, uniqueKeyField = "id", values = $bindable(undefined), width = "32rem" } = $props();
6
+ const autoTitle = $derived(deriveAutoTitle({
7
+ request,
8
+ title,
9
+ uniqueKeyField,
10
+ values
11
+ }));
12
+ const animBackdrop = "transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100";
13
+ const animContent = "transition transition-discrete opacity-0 translate-x-full starting:data-[state=open]:opacity-0 starting:data-[state=open]:translate-x-full data-[state=open]:opacity-100 data-[state=open]:translate-x-0";
14
+ const overlayZ = createOverlayZIndex("drawer", () => opened);
79
15
  </script>
80
16
 
81
17
  <Dialog
@@ -91,11 +27,11 @@
91
27
  <Portal>
92
28
  <Dialog.Backdrop
93
29
  class="fixed inset-0 bg-black/50 backdrop-blur-sm {animBackdrop}"
94
- style={`z-index:${backdropZ};`}
30
+ style={`z-index:${overlayZ.backdropZ};`}
95
31
  />
96
32
  <Dialog.Positioner
97
33
  class="fixed inset-0 flex justify-end"
98
- style={`z-index:${contentZ};`}
34
+ style={`z-index:${overlayZ.contentZ};`}
99
35
  >
100
36
  <Dialog.Content
101
37
  class="card bg-surface-100-900 shadow-2xl h-full flex flex-col overflow-hidden rounded-none rounded-l-container-token {animContent}"
@@ -1,93 +1,104 @@
1
- <script lang="ts">
2
-
3
- import FormerDrawer from './FormerDrawer.svelte';
4
- import type { FormRequestType } from './types';
5
- import TextInputCtrl from '../FormerControllers/TextInputCtrl.svelte';
6
- import PasswordInputCtrl from '../FormerControllers/PasswordInputCtrl.svelte';
7
- import NumberInputCtrl from '../FormerControllers/NumberInputCtrl.svelte';
8
- import NativeSelectCtrl from '../FormerControllers/NativeSelectCtrl.svelte';
9
- import TextAreaCtrl from '../FormerControllers/TextAreaCtrl.svelte';
10
- import SwitchCtrl from '../FormerControllers/SwitchCtrl.svelte';
11
- import Boxer from '../Boxer/Boxer.svelte';
12
-
13
- interface UserForm {
14
- id?: number;
15
- firstName: string;
16
- lastName: string;
17
- email: string;
18
- password: string;
19
- age?: number;
20
- role: string;
21
- department: string;
22
- skills: string[];
23
- bio: string;
24
- website: string;
25
- emailNotifications: boolean;
26
- active: boolean;
1
+ <script lang="ts">import FormerDrawer from "./FormerDrawer.svelte";
2
+ import TextInputCtrl from "../FormerControllers/TextInputCtrl.svelte";
3
+ import PasswordInputCtrl from "../FormerControllers/PasswordInputCtrl.svelte";
4
+ import NumberInputCtrl from "../FormerControllers/NumberInputCtrl.svelte";
5
+ import NativeSelectCtrl from "../FormerControllers/NativeSelectCtrl.svelte";
6
+ import TextAreaCtrl from "../FormerControllers/TextAreaCtrl.svelte";
7
+ import SwitchCtrl from "../FormerControllers/SwitchCtrl.svelte";
8
+ import Boxer from "../Boxer/Boxer.svelte";
9
+ const { request = "insert" } = $props();
10
+ const emptyUser = {
11
+ firstName: "",
12
+ lastName: "",
13
+ email: "",
14
+ password: "",
15
+ age: undefined,
16
+ role: "",
17
+ department: "",
18
+ skills: [],
19
+ bio: "",
20
+ website: "",
21
+ emailNotifications: true,
22
+ active: true
23
+ };
24
+ const filledUser = {
25
+ id: 1,
26
+ firstName: "Jane",
27
+ lastName: "Smith",
28
+ email: "jane.smith@example.com",
29
+ password: "",
30
+ age: 32,
31
+ role: "admin",
32
+ department: "engineering",
33
+ skills: ["typescript", "svelte"],
34
+ bio: "Senior software engineer with 10 years of experience building scalable systems.",
35
+ website: "https://janesmith.dev",
36
+ emailNotifications: true,
37
+ active: true
38
+ };
39
+ const roleOptions = [
40
+ {
41
+ label: "Admin",
42
+ value: "admin"
43
+ },
44
+ {
45
+ label: "Editor",
46
+ value: "editor"
47
+ },
48
+ {
49
+ label: "Viewer",
50
+ value: "viewer"
27
51
  }
28
-
29
- export interface Props {
30
- request?: FormRequestType;
52
+ ];
53
+ const departmentOptions = [
54
+ {
55
+ label: "Engineering",
56
+ value: "engineering"
57
+ },
58
+ {
59
+ label: "Product",
60
+ value: "product"
61
+ },
62
+ {
63
+ label: "Design",
64
+ value: "design"
65
+ },
66
+ {
67
+ label: "Marketing",
68
+ value: "marketing"
69
+ },
70
+ {
71
+ label: "Operations",
72
+ value: "operations"
31
73
  }
32
-
33
- const { request = 'insert' }: Props = $props();
34
-
35
- const emptyUser: UserForm = {
36
- firstName: '',
37
- lastName: '',
38
- email: '',
39
- password: '',
40
- age: undefined,
41
- role: '',
42
- department: '',
43
- skills: [],
44
- bio: '',
45
- website: '',
46
- emailNotifications: true,
47
- active: true,
48
- };
49
-
50
- const filledUser: UserForm = {
51
- id: 1,
52
- firstName: 'Jane',
53
- lastName: 'Smith',
54
- email: 'jane.smith@example.com',
55
- password: '',
56
- age: 32,
57
- role: 'admin',
58
- department: 'engineering',
59
- skills: ['typescript', 'svelte'],
60
- bio: 'Senior software engineer with 10 years of experience building scalable systems.',
61
- website: 'https://janesmith.dev',
62
- emailNotifications: true,
63
- active: true,
64
- };
65
-
66
- const roleOptions = [
67
- { label: 'Admin', value: 'admin' },
68
- { label: 'Editor', value: 'editor' },
69
- { label: 'Viewer', value: 'viewer' },
70
- ];
71
-
72
- const departmentOptions = [
73
- { label: 'Engineering', value: 'engineering' },
74
- { label: 'Product', value: 'product' },
75
- { label: 'Design', value: 'design' },
76
- { label: 'Marketing', value: 'marketing' },
77
- { label: 'Operations', value: 'operations' },
78
- ];
79
-
80
- const skillOptions = [
81
- { label: 'Svelte', value: 'svelte' },
82
- { label: 'TypeScript', value: 'typescript' },
83
- { label: 'Node.js', value: 'nodejs' },
84
- { label: 'Testing', value: 'testing' },
85
- { label: 'UX', value: 'ux' },
86
- ];
87
-
88
- let values = $state<UserForm>(request === 'insert' ? { ...emptyUser } : { ...filledUser });
89
- let lastSaved = $state<UserForm | undefined>(undefined);
90
- let opened = $state(false);
74
+ ];
75
+ const skillOptions = [
76
+ {
77
+ label: "Svelte",
78
+ value: "svelte"
79
+ },
80
+ {
81
+ label: "TypeScript",
82
+ value: "typescript"
83
+ },
84
+ {
85
+ label: "Node.js",
86
+ value: "nodejs"
87
+ },
88
+ {
89
+ label: "Testing",
90
+ value: "testing"
91
+ },
92
+ {
93
+ label: "UX",
94
+ value: "ux"
95
+ }
96
+ ];
97
+ // eslint-disable-next-line svelte/no-unused-svelte-ignore
98
+ // svelte-ignore state_referenced_locally -- initial value is intentional (sets up form state once)
99
+ let values = $state(request === "insert" ? { ...emptyUser } : { ...filledUser });
100
+ let lastSaved = $state(undefined);
101
+ let opened = $state(false);
91
102
  </script>
92
103
 
93
104
  <div class="p-8 space-y-6">
@@ -213,7 +224,6 @@
213
224
  dataSource="local"
214
225
  disablePortal
215
226
  multiSelect
216
- searchable
217
227
  clearable
218
228
  placeholder="Search skills..."
219
229
  disabled={isReadonly}
@@ -1,75 +1,17 @@
1
- <script lang="ts">
2
- /* eslint-disable @typescript-eslint/no-explicit-any */
3
- import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
4
- import { registerOverlay } from '../OverlayStack';
5
- import Former from './Former.svelte';
6
- import type { FormerProps, FormRequestType } from './types';
7
-
8
- export interface Props extends FormerProps {
9
- /**
10
- * Override the auto-generated dialog title.
11
- * When omitted the title is derived from the request type and the unique key value:
12
- * insert → "New Record"
13
- * update → "Edit Record {key}"
14
- * delete → "Delete Record {key}"
15
- */
16
- title?: string;
17
- }
18
-
19
- let {
20
- afterGet,
21
- afterSave,
22
- beforeSave,
23
- children,
24
- id,
25
- keepOpen = $bindable(false),
26
- layout,
27
- onAPICall,
28
- onChange,
29
- onClose,
30
- onConfirmDelete,
31
- onError,
32
- onOpen,
33
- opened = $bindable(false),
34
- primeData,
35
- request = $bindable<FormRequestType>('insert'),
36
- title,
37
- uniqueKeyField = 'id',
38
- values = $bindable<any>(undefined),
39
- }: Props = $props();
40
-
41
- const autoTitle = $derived(
42
- title ??
43
- (request === 'delete'
44
- ? `Delete Record${(values as any)?.[uniqueKeyField] ? ` — ${(values as any)[uniqueKeyField]}` : ''}`
45
- : request === 'insert'
46
- ? 'New Record'
47
- : `Edit Record${(values as any)?.[uniqueKeyField] ? ` — ${(values as any)[uniqueKeyField]}` : ''}`)
48
- );
49
-
50
- const animBackdrop =
51
- 'transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100';
52
- const animContent =
53
- 'transition transition-discrete opacity-0 scale-95 starting:data-[state=open]:opacity-0 starting:data-[state=open]:scale-95 data-[state=open]:opacity-100 data-[state=open]:scale-100';
54
-
55
- let backdropZ = $state(1000);
56
- let contentZ = $state(1010);
57
-
58
- $effect(() => {
59
- if (!opened) {
60
- return;
61
- }
62
-
63
- const overlay = registerOverlay({ kind: 'dialog', mount: 'portal' });
64
- backdropZ = overlay.layer.backdrop;
65
- contentZ = overlay.layer.content;
66
-
67
- return () => {
68
- overlay.unregister();
69
- backdropZ = 1000;
70
- contentZ = 1010;
71
- };
72
- });
1
+ <script lang="ts">/* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { Dialog, Portal } from "@skeletonlabs/skeleton-svelte";
3
+ import Former from "./Former.svelte";
4
+ import { createOverlayZIndex, deriveAutoTitle } from "./formerOverlayHelpers.svelte";
5
+ let { afterGet, afterSave, beforeSave, children, id, keepOpen = $bindable(false), layout, onAPICall, onChange, onClose, onConfirmDelete, onError, onOpen, opened = $bindable(false), primeData, request = $bindable("insert"), title, uniqueKeyField = "id", values = $bindable(undefined) } = $props();
6
+ const autoTitle = $derived(deriveAutoTitle({
7
+ request,
8
+ title,
9
+ uniqueKeyField,
10
+ values
11
+ }));
12
+ const animBackdrop = "transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100";
13
+ const animContent = "transition transition-discrete opacity-0 scale-95 starting:data-[state=open]:opacity-0 starting:data-[state=open]:scale-95 data-[state=open]:opacity-100 data-[state=open]:scale-100";
14
+ const overlayZ = createOverlayZIndex("dialog", () => opened);
73
15
  </script>
74
16
 
75
17
  <Dialog
@@ -85,9 +27,9 @@
85
27
  <Portal>
86
28
  <Dialog.Backdrop
87
29
  class="fixed inset-0 bg-black/50 backdrop-blur-sm {animBackdrop}"
88
- style={`z-index:${backdropZ};`}
30
+ style={`z-index:${overlayZ.backdropZ};`}
89
31
  />
90
- <Dialog.Positioner class="fixed inset-0 flex items-center justify-center p-4" style={`z-index:${contentZ};`}>
32
+ <Dialog.Positioner class="fixed inset-0 flex items-center justify-center p-4" style={`z-index:${overlayZ.contentZ};`}>
91
33
  <Dialog.Content
92
34
  class="card bg-surface-100-900 shadow-2xl w-full max-w-2xl max-h-[90vh] flex flex-col overflow-hidden {animContent}"
93
35
  >