@fivem-nui/svelte-components 0.0.0-stage → 1.0.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 (143) hide show
  1. package/README.md +101 -2
  2. package/dist/components/actions/NuiButton.svelte +292 -0
  3. package/dist/components/actions/NuiButton.svelte.d.ts +60 -0
  4. package/dist/components/data/NuiBadge.svelte +277 -0
  5. package/dist/components/data/NuiBadge.svelte.d.ts +74 -0
  6. package/dist/components/data/NuiCodeBlock.svelte +256 -0
  7. package/dist/components/data/NuiCodeBlock.svelte.d.ts +49 -0
  8. package/dist/components/data/NuiList.svelte +341 -0
  9. package/dist/components/data/NuiList.svelte.d.ts +52 -0
  10. package/dist/components/data/NuiProgressBar.svelte +264 -0
  11. package/dist/components/data/NuiProgressBar.svelte.d.ts +51 -0
  12. package/dist/components/data/NuiRichText.svelte +260 -0
  13. package/dist/components/data/NuiRichText.svelte.d.ts +33 -0
  14. package/dist/components/data/NuiTable.svelte +470 -0
  15. package/dist/components/data/NuiTable.svelte.d.ts +53 -0
  16. package/dist/components/data/chart/NuiChart.svelte +384 -0
  17. package/dist/components/data/chart/NuiChart.svelte.d.ts +49 -0
  18. package/dist/components/data/chart/color.d.ts +9 -0
  19. package/dist/components/data/chart/color.js +78 -0
  20. package/dist/components/data/chart/index.d.ts +10 -0
  21. package/dist/components/data/chart/index.js +10 -0
  22. package/dist/components/data/chart/registry.d.ts +14 -0
  23. package/dist/components/data/chart/registry.js +53 -0
  24. package/dist/components/data/chart/renderers/bar.d.ts +8 -0
  25. package/dist/components/data/chart/renderers/bar.js +79 -0
  26. package/dist/components/data/chart/renderers/base.d.ts +18 -0
  27. package/dist/components/data/chart/renderers/base.js +10 -0
  28. package/dist/components/data/chart/renderers/line.d.ts +8 -0
  29. package/dist/components/data/chart/renderers/line.js +89 -0
  30. package/dist/components/data/chart/renderers/pie.d.ts +10 -0
  31. package/dist/components/data/chart/renderers/pie.js +55 -0
  32. package/dist/components/data/chart/scale.d.ts +22 -0
  33. package/dist/components/data/chart/scale.js +101 -0
  34. package/dist/components/data/chart/types.d.ts +84 -0
  35. package/dist/components/data/chart/types.js +1 -0
  36. package/dist/components/data/chart/validator.d.ts +10 -0
  37. package/dist/components/data/chart/validator.js +82 -0
  38. package/dist/components/forms/NuiCheckbox.svelte +218 -0
  39. package/dist/components/forms/NuiCheckbox.svelte.d.ts +37 -0
  40. package/dist/components/forms/NuiDatepicker.svelte +755 -0
  41. package/dist/components/forms/NuiDatepicker.svelte.d.ts +34 -0
  42. package/dist/components/forms/NuiFileInput.svelte +1047 -0
  43. package/dist/components/forms/NuiFileInput.svelte.d.ts +93 -0
  44. package/dist/components/forms/NuiFileInput.types.d.ts +28 -0
  45. package/dist/components/forms/NuiFileInput.types.js +1 -0
  46. package/dist/components/forms/NuiForm.svelte +391 -0
  47. package/dist/components/forms/NuiForm.svelte.d.ts +69 -0
  48. package/dist/components/forms/NuiInput.svelte +296 -0
  49. package/dist/components/forms/NuiInput.svelte.d.ts +62 -0
  50. package/dist/components/forms/NuiRadioGroup.svelte +238 -0
  51. package/dist/components/forms/NuiRadioGroup.svelte.d.ts +47 -0
  52. package/dist/components/forms/NuiSelect.svelte +819 -0
  53. package/dist/components/forms/NuiSelect.svelte.d.ts +49 -0
  54. package/dist/components/layout/NuiCard.svelte +314 -0
  55. package/dist/components/layout/NuiCard.svelte.d.ts +48 -0
  56. package/dist/components/layout/NuiCardGrid.svelte +98 -0
  57. package/dist/components/layout/NuiCardGrid.svelte.d.ts +22 -0
  58. package/dist/components/layout/NuiFlex.svelte +121 -0
  59. package/dist/components/layout/NuiFlex.svelte.d.ts +23 -0
  60. package/dist/components/layout/NuiGrid.svelte +66 -0
  61. package/dist/components/layout/NuiGrid.svelte.d.ts +14 -0
  62. package/dist/components/layout/NuiStack.svelte +138 -0
  63. package/dist/components/layout/NuiStack.svelte.d.ts +26 -0
  64. package/dist/components/navigation/NuiAccordion.svelte +323 -0
  65. package/dist/components/navigation/NuiAccordion.svelte.d.ts +38 -0
  66. package/dist/components/navigation/NuiBreadcrumbs.svelte +133 -0
  67. package/dist/components/navigation/NuiBreadcrumbs.svelte.d.ts +19 -0
  68. package/dist/components/navigation/NuiMenu.svelte +596 -0
  69. package/dist/components/navigation/NuiMenu.svelte.d.ts +28 -0
  70. package/dist/components/navigation/NuiPagination.svelte +306 -0
  71. package/dist/components/navigation/NuiPagination.svelte.d.ts +40 -0
  72. package/dist/components/navigation/NuiSidebar.svelte +186 -0
  73. package/dist/components/navigation/NuiSidebar.svelte.d.ts +26 -0
  74. package/dist/components/navigation/NuiTabs.svelte +249 -0
  75. package/dist/components/navigation/NuiTabs.svelte.d.ts +31 -0
  76. package/dist/components/overlay/NuiDialog.svelte +118 -0
  77. package/dist/components/overlay/NuiDialog.svelte.d.ts +34 -0
  78. package/dist/components/overlay/NuiModal.svelte +992 -0
  79. package/dist/components/overlay/NuiModal.svelte.d.ts +72 -0
  80. package/dist/components/overlay/NuiTooltip.svelte +159 -0
  81. package/dist/components/overlay/NuiTooltip.svelte.d.ts +13 -0
  82. package/dist/composables/useClickOutside.d.ts +43 -0
  83. package/dist/composables/useClickOutside.js +73 -0
  84. package/dist/composables/useFormValidation.d.ts +23 -0
  85. package/dist/composables/useFormValidation.js +72 -0
  86. package/dist/composables/useIdle.svelte.d.ts +18 -0
  87. package/dist/composables/useIdle.svelte.js +144 -0
  88. package/dist/composables/useKeyboardShortcut.svelte.d.ts +114 -0
  89. package/dist/composables/useKeyboardShortcut.svelte.js +153 -0
  90. package/dist/composables/useLocalStorage.svelte.d.ts +22 -0
  91. package/dist/composables/useLocalStorage.svelte.js +105 -0
  92. package/dist/composables/useMediaQuery.svelte.d.ts +51 -0
  93. package/dist/composables/useMediaQuery.svelte.js +80 -0
  94. package/dist/index.d.ts +46 -0
  95. package/dist/index.js +42 -0
  96. package/package.json +58 -3
  97. package/src/components/actions/NuiButton.svelte +292 -0
  98. package/src/components/data/NuiBadge.svelte +277 -0
  99. package/src/components/data/NuiCodeBlock.svelte +256 -0
  100. package/src/components/data/NuiList.svelte +341 -0
  101. package/src/components/data/NuiProgressBar.svelte +264 -0
  102. package/src/components/data/NuiRichText.svelte +260 -0
  103. package/src/components/data/NuiTable.svelte +470 -0
  104. package/src/components/data/chart/NuiChart.svelte +384 -0
  105. package/src/components/data/chart/color.ts +83 -0
  106. package/src/components/data/chart/index.ts +10 -0
  107. package/src/components/data/chart/registry.ts +71 -0
  108. package/src/components/data/chart/renderers/bar.ts +90 -0
  109. package/src/components/data/chart/renderers/base.ts +32 -0
  110. package/src/components/data/chart/renderers/line.ts +99 -0
  111. package/src/components/data/chart/renderers/pie.ts +66 -0
  112. package/src/components/data/chart/scale.ts +139 -0
  113. package/src/components/data/chart/types.ts +98 -0
  114. package/src/components/data/chart/validator.ts +98 -0
  115. package/src/components/forms/NuiCheckbox.svelte +218 -0
  116. package/src/components/forms/NuiDatepicker.svelte +755 -0
  117. package/src/components/forms/NuiFileInput.svelte +1047 -0
  118. package/src/components/forms/NuiFileInput.types.ts +29 -0
  119. package/src/components/forms/NuiForm.svelte +391 -0
  120. package/src/components/forms/NuiInput.svelte +296 -0
  121. package/src/components/forms/NuiRadioGroup.svelte +238 -0
  122. package/src/components/forms/NuiSelect.svelte +819 -0
  123. package/src/components/layout/NuiCard.svelte +314 -0
  124. package/src/components/layout/NuiCardGrid.svelte +98 -0
  125. package/src/components/layout/NuiFlex.svelte +121 -0
  126. package/src/components/layout/NuiGrid.svelte +66 -0
  127. package/src/components/layout/NuiStack.svelte +138 -0
  128. package/src/components/navigation/NuiAccordion.svelte +323 -0
  129. package/src/components/navigation/NuiBreadcrumbs.svelte +133 -0
  130. package/src/components/navigation/NuiMenu.svelte +596 -0
  131. package/src/components/navigation/NuiPagination.svelte +306 -0
  132. package/src/components/navigation/NuiSidebar.svelte +186 -0
  133. package/src/components/navigation/NuiTabs.svelte +249 -0
  134. package/src/components/overlay/NuiDialog.svelte +118 -0
  135. package/src/components/overlay/NuiModal.svelte +992 -0
  136. package/src/components/overlay/NuiTooltip.svelte +159 -0
  137. package/src/composables/useClickOutside.ts +132 -0
  138. package/src/composables/useFormValidation.ts +105 -0
  139. package/src/composables/useIdle.svelte.ts +191 -0
  140. package/src/composables/useKeyboardShortcut.svelte.ts +278 -0
  141. package/src/composables/useLocalStorage.svelte.ts +137 -0
  142. package/src/composables/useMediaQuery.svelte.ts +102 -0
  143. package/src/index.ts +66 -0
@@ -0,0 +1,238 @@
1
+ <script module lang="ts">
2
+ export interface NuiRadioOption {
3
+ /**
4
+ * Unique value identifying this option.
5
+ * Must be unique within the options array to prevent key conflicts in Svelte's
6
+ * `{#each}` block and ambiguous selection behavior.
7
+ */
8
+ value: string;
9
+ /** text label for the radio option. */
10
+ label: string;
11
+ /** Optional secondary description text displayed below the label. */
12
+ description?: string;
13
+ /** Whether this individual option is disabled. */
14
+ disabled?: boolean;
15
+ }
16
+ </script>
17
+
18
+ <script lang="ts">
19
+ import { nui } from "@fivem-nui/svelte";
20
+ import type { SvelteNuiClient } from "@fivem-nui/svelte";
21
+
22
+ interface Props {
23
+ /** NUI event name emitted when an option is selected. */
24
+ eventName?: string;
25
+ /** SvelteNuiClient instance used to dispatch NUI events. */
26
+ client?: SvelteNuiClient;
27
+ /** Currently selected value. Supports two-way binding via `bind:value`. */
28
+ value?: string;
29
+ /** Text rendered inside the `<legend>` element. */
30
+ label?: string;
31
+ /**
32
+ * Available radio options.
33
+ *
34
+ * Each option's `value` must be unique within the array —
35
+ * duplicate values will cause key conflicts in Svelte's `{#each}` block and
36
+ * ambiguous selection behavior.
37
+ */
38
+ options?: NuiRadioOption[];
39
+ /** Whether the entire radio group is disabled. */
40
+ disabled?: boolean;
41
+ /**
42
+ * HTML `name` attribute for the radio group.
43
+ *
44
+ * If omitted or an empty string, a unique name is generated per component instance
45
+ * via `$props.id()` to prevent cross-group interference when multiple NuiRadioGroup
46
+ * components coexist on the same page. If a non-empty name is explicitly provided,
47
+ * it takes precedence.
48
+ */
49
+ name?: string;
50
+ }
51
+
52
+ const autoId = $props.id();
53
+
54
+ let {
55
+ eventName = "",
56
+ client = nui,
57
+ value = $bindable(""),
58
+ label = "",
59
+ options = [],
60
+ disabled = false,
61
+ name,
62
+ }: Props = $props();
63
+
64
+ const groupName = $derived(name || `nui-radio-${autoId}`);
65
+
66
+ // Warn about duplicate option values to prevent key conflicts in {#each} and ambiguous selection
67
+ $effect(() => {
68
+ const seen = new Set<string>();
69
+ for (const opt of options) {
70
+ if (seen.has(opt.value)) {
71
+ console.warn(
72
+ `[fivem-nui-components] NuiRadioGroup: Duplicate option value '${opt.value}' detected. Option values must be unique within the group.`,
73
+ );
74
+ break;
75
+ }
76
+ seen.add(opt.value);
77
+ }
78
+ });
79
+
80
+ /**
81
+ * Safely sends an event via the NUI client, catching synchronous exceptions.
82
+ *
83
+ * Note: Selection is optimistic the bound `value` is updated immediately and
84
+ * does not revert if network transport fails.
85
+ */
86
+ function safeSend(event: string, data: unknown) {
87
+ if (!event) return;
88
+ try {
89
+ client.send(event, data);
90
+ } catch (err) {
91
+ console.error(
92
+ `[fivem-nui-components] NuiRadioGroup: Failed to send event '${event}':`,
93
+ err,
94
+ );
95
+ }
96
+ }
97
+
98
+ function select(option: NuiRadioOption) {
99
+ if (disabled || option.disabled) return;
100
+ value = option.value;
101
+ safeSend(eventName, { value: option.value, label: option.label });
102
+ }
103
+ </script>
104
+
105
+ <fieldset class="nui-radiogroup" {disabled}>
106
+ {#if label}<legend class="nui-radiogroup__label">{label}</legend>{/if}
107
+
108
+ {#each options as option, i (`${option.value}-${i}`)}
109
+ <label
110
+ class="nui-radio-option"
111
+ class:is-disabled={option.disabled || disabled}
112
+ class:is-checked={value === option.value}
113
+ >
114
+ <input
115
+ class="nui-radio-option__input"
116
+ type="radio"
117
+ name={groupName}
118
+ value={option.value}
119
+ checked={value === option.value}
120
+ disabled={option.disabled || disabled}
121
+ onchange={() => select(option)}
122
+ />
123
+ <span class="nui-radio-track" aria-hidden="true"
124
+ ><span class="nui-radio-dot"></span></span
125
+ >
126
+ <span class="nui-radio-text">
127
+ <span class="nui-radio-label">{option.label}</span>
128
+ {#if option.description}
129
+ <span class="nui-radio-description">{option.description}</span>
130
+ {/if}
131
+ </span>
132
+ </label>
133
+ {/each}
134
+ </fieldset>
135
+
136
+ <style>
137
+ .nui-radiogroup {
138
+ display: flex;
139
+ flex-direction: column;
140
+ gap: 0.375rem;
141
+ margin: 0;
142
+ padding: 0;
143
+ border: 0;
144
+ font-family: inherit;
145
+ }
146
+
147
+ .nui-radiogroup__label {
148
+ padding: 0 0 0.25rem;
149
+ font-size: 0.8125rem;
150
+ font-weight: 600;
151
+ opacity: 0.75;
152
+ color: var(--nui-fg, #fafafa);
153
+ }
154
+
155
+ .nui-radio-option {
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 0.625rem;
159
+ padding: 0.4rem 0.5rem;
160
+ border-radius: var(--nui-radius, 0.375rem);
161
+ cursor: pointer;
162
+ color: var(--nui-fg, #fafafa);
163
+ transition: background 0.15s ease;
164
+ user-select: none;
165
+ }
166
+
167
+ .nui-radio-option:hover:not(.is-disabled) {
168
+ background: var(--nui-hover, rgb(255 255 255 / 0.05));
169
+ }
170
+
171
+ .nui-radio-option.is-disabled {
172
+ opacity: 0.45;
173
+ cursor: not-allowed;
174
+ }
175
+
176
+ /* Visually hidden using standard technique — accessible to screen readers & keyboard */
177
+ .nui-radio-option__input {
178
+ position: absolute;
179
+ width: 1px;
180
+ height: 1px;
181
+ padding: 0;
182
+ margin: -1px;
183
+ overflow: hidden;
184
+ clip: rect(0, 0, 0, 0);
185
+ clip-path: inset(50%);
186
+ border: 0;
187
+ white-space: nowrap;
188
+ }
189
+
190
+ /* Visible focus indicator on the custom radio track when navigating via keyboard */
191
+ .nui-radio-option__input:focus-visible + .nui-radio-track {
192
+ outline: 2px solid var(--nui-primary, #3b82f6);
193
+ outline-offset: 3px;
194
+ }
195
+
196
+ .nui-radio-track {
197
+ position: relative;
198
+ flex: none;
199
+ width: 1.1rem;
200
+ height: 1.1rem;
201
+ border: 2px solid var(--nui-border, #52525b);
202
+ border-radius: 50%;
203
+ transition: border-color 0.15s ease;
204
+ box-sizing: border-box;
205
+ }
206
+
207
+ .nui-radio-option.is-checked .nui-radio-track {
208
+ border-color: var(--nui-primary, #3b82f6);
209
+ }
210
+
211
+ .nui-radio-dot {
212
+ position: absolute;
213
+ inset: 2px;
214
+ border-radius: 50%;
215
+ background: var(--nui-primary, #3b82f6);
216
+ transform: scale(0);
217
+ transition: transform 0.15s ease;
218
+ }
219
+
220
+ .nui-radio-option.is-checked .nui-radio-dot {
221
+ transform: scale(1);
222
+ }
223
+
224
+ .nui-radio-text {
225
+ display: flex;
226
+ flex-direction: column;
227
+ line-height: 1.3;
228
+ }
229
+
230
+ .nui-radio-label {
231
+ font-size: 0.875rem;
232
+ }
233
+
234
+ .nui-radio-description {
235
+ font-size: 0.75rem;
236
+ opacity: 0.65;
237
+ }
238
+ </style>