@simplysm/solid 13.0.72 → 13.0.75

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 (210) hide show
  1. package/README.md +209 -202
  2. package/dist/components/data/calendar/Calendar.d.ts.map +1 -1
  3. package/dist/components/data/calendar/Calendar.js +3 -11
  4. package/dist/components/data/calendar/Calendar.js.map +2 -2
  5. package/dist/components/data/sheet/DataSheet.js +10 -10
  6. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  7. package/dist/components/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
  8. package/dist/components/data/sheet/DataSheetConfigDialog.js +27 -9
  9. package/dist/components/data/sheet/DataSheetConfigDialog.js.map +2 -2
  10. package/dist/components/disclosure/Dialog.d.ts +1 -1
  11. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  12. package/dist/components/disclosure/Dialog.js +5 -5
  13. package/dist/components/disclosure/Dialog.js.map +2 -2
  14. package/dist/components/disclosure/dialogZIndex.d.ts +1 -1
  15. package/dist/components/features/crud-detail/CrudDetail.js +23 -23
  16. package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
  17. package/dist/components/features/crud-sheet/CrudSheet.js +49 -49
  18. package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
  19. package/dist/components/features/crud-sheet/types.d.ts +4 -4
  20. package/dist/components/features/crud-sheet/types.d.ts.map +1 -1
  21. package/dist/components/features/data-select-button/DataSelectButton.d.ts +25 -7
  22. package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
  23. package/dist/components/features/data-select-button/DataSelectButton.js +27 -12
  24. package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
  25. package/dist/components/features/permission-table/PermissionTable.js +4 -4
  26. package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
  27. package/dist/components/features/shared-data/SharedDataSelect.d.ts +22 -10
  28. package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
  29. package/dist/components/features/shared-data/SharedDataSelect.js +113 -29
  30. package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
  31. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts +3 -3
  32. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts.map +1 -1
  33. package/dist/components/features/shared-data/SharedDataSelectButton.js.map +1 -1
  34. package/dist/components/features/shared-data/SharedDataSelectList.js +5 -4
  35. package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
  36. package/dist/components/feedback/notification/NotificationBanner.js +3 -3
  37. package/dist/components/feedback/notification/NotificationBanner.js.map +2 -2
  38. package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
  39. package/dist/components/feedback/notification/NotificationBell.js +12 -5
  40. package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
  41. package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
  42. package/dist/components/feedback/notification/NotificationProvider.js +3 -1
  43. package/dist/components/feedback/notification/NotificationProvider.js.map +2 -2
  44. package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
  45. package/dist/components/form-control/ThemeToggle.js +9 -6
  46. package/dist/components/form-control/ThemeToggle.js.map +2 -2
  47. package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
  48. package/dist/components/form-control/checkbox/Checkbox.js +3 -1
  49. package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
  50. package/dist/components/form-control/checkbox/CheckboxGroup.js +1 -1
  51. package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
  52. package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
  53. package/dist/components/form-control/checkbox/Radio.js +3 -1
  54. package/dist/components/form-control/checkbox/Radio.js.map +2 -2
  55. package/dist/components/form-control/checkbox/RadioGroup.js +1 -1
  56. package/dist/components/form-control/checkbox/RadioGroup.js.map +2 -2
  57. package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
  58. package/dist/components/form-control/color-picker/ColorPicker.js +3 -1
  59. package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
  60. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  61. package/dist/components/form-control/combobox/Combobox.js +9 -5
  62. package/dist/components/form-control/combobox/Combobox.js.map +2 -2
  63. package/dist/components/form-control/date-range-picker/DateRangePicker.js +9 -9
  64. package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
  65. package/dist/components/form-control/editor/EditorToolbar.js +3 -3
  66. package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
  67. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  68. package/dist/components/form-control/field/DatePicker.js +9 -3
  69. package/dist/components/form-control/field/DatePicker.js.map +2 -2
  70. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  71. package/dist/components/form-control/field/DateTimePicker.js +9 -3
  72. package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
  73. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  74. package/dist/components/form-control/field/NumberInput.js +9 -3
  75. package/dist/components/form-control/field/NumberInput.js.map +2 -2
  76. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  77. package/dist/components/form-control/field/TextInput.js +10 -4
  78. package/dist/components/form-control/field/TextInput.js.map +2 -2
  79. package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
  80. package/dist/components/form-control/field/Textarea.js +9 -3
  81. package/dist/components/form-control/field/Textarea.js.map +2 -2
  82. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  83. package/dist/components/form-control/field/TimePicker.js +9 -3
  84. package/dist/components/form-control/field/TimePicker.js.map +2 -2
  85. package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
  86. package/dist/components/form-control/numpad/Numpad.js +5 -1
  87. package/dist/components/form-control/numpad/Numpad.js.map +2 -2
  88. package/dist/components/form-control/select/Select.js +7 -7
  89. package/dist/components/form-control/select/Select.js.map +2 -2
  90. package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
  91. package/dist/components/form-control/state-preset/StatePreset.js +42 -20
  92. package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
  93. package/dist/components/layout/sidebar/SidebarContainer.js +3 -3
  94. package/dist/components/layout/sidebar/SidebarContainer.js.map +2 -2
  95. package/dist/components/layout/sidebar/SidebarMenu.d.ts.map +1 -1
  96. package/dist/components/layout/sidebar/SidebarMenu.js +5 -2
  97. package/dist/components/layout/sidebar/SidebarMenu.js.map +2 -2
  98. package/dist/components/layout/topbar/Topbar.js +3 -4
  99. package/dist/components/layout/topbar/Topbar.js.map +2 -2
  100. package/dist/components/layout/topbar/TopbarMenu.js +3 -3
  101. package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
  102. package/dist/hooks/createSelectionGroup.d.ts +2 -2
  103. package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
  104. package/dist/hooks/createSelectionGroup.js +5 -2
  105. package/dist/hooks/createSelectionGroup.js.map +2 -2
  106. package/dist/providers/i18n/I18nContext.d.ts +0 -4
  107. package/dist/providers/i18n/I18nContext.d.ts.map +1 -1
  108. package/dist/providers/i18n/I18nContext.js +1 -5
  109. package/dist/providers/i18n/I18nContext.js.map +2 -2
  110. package/dist/providers/i18n/locales/en.d.ts +38 -0
  111. package/dist/providers/i18n/locales/en.d.ts.map +1 -1
  112. package/dist/providers/i18n/locales/en.js +39 -1
  113. package/dist/providers/i18n/locales/en.js.map +1 -1
  114. package/dist/providers/i18n/locales/ko.d.ts +38 -0
  115. package/dist/providers/i18n/locales/ko.d.ts.map +1 -1
  116. package/dist/providers/i18n/locales/ko.js +39 -1
  117. package/dist/providers/i18n/locales/ko.js.map +1 -1
  118. package/package.json +6 -6
  119. package/src/components/data/calendar/Calendar.tsx +3 -4
  120. package/src/components/data/sheet/DataSheet.tsx +11 -11
  121. package/src/components/data/sheet/DataSheetConfigDialog.tsx +12 -10
  122. package/src/components/data/sheet/types.ts +1 -1
  123. package/src/components/disclosure/Dialog.tsx +10 -10
  124. package/src/components/disclosure/dialogZIndex.ts +1 -1
  125. package/src/components/features/crud-detail/CrudDetail.tsx +25 -25
  126. package/src/components/features/crud-sheet/CrudSheet.tsx +53 -53
  127. package/src/components/features/crud-sheet/types.ts +4 -4
  128. package/src/components/features/data-select-button/DataSelectButton.tsx +51 -21
  129. package/src/components/features/permission-table/PermissionTable.tsx +3 -3
  130. package/src/components/features/shared-data/SharedDataSelect.tsx +172 -33
  131. package/src/components/features/shared-data/SharedDataSelectButton.tsx +3 -2
  132. package/src/components/features/shared-data/SharedDataSelectList.tsx +4 -4
  133. package/src/components/feedback/notification/NotificationBanner.tsx +3 -3
  134. package/src/components/feedback/notification/NotificationBell.tsx +6 -4
  135. package/src/components/feedback/notification/NotificationProvider.tsx +3 -1
  136. package/src/components/form-control/ThemeToggle.tsx +10 -6
  137. package/src/components/form-control/checkbox/Checkbox.tsx +4 -1
  138. package/src/components/form-control/checkbox/CheckboxGroup.tsx +1 -1
  139. package/src/components/form-control/checkbox/Radio.tsx +4 -1
  140. package/src/components/form-control/checkbox/RadioGroup.tsx +1 -1
  141. package/src/components/form-control/color-picker/ColorPicker.tsx +4 -1
  142. package/src/components/form-control/combobox/Combobox.tsx +6 -3
  143. package/src/components/form-control/date-range-picker/DateRangePicker.tsx +8 -8
  144. package/src/components/form-control/editor/EditorToolbar.tsx +23 -23
  145. package/src/components/form-control/field/DatePicker.tsx +6 -3
  146. package/src/components/form-control/field/DateTimePicker.tsx +6 -3
  147. package/src/components/form-control/field/NumberInput.tsx +6 -3
  148. package/src/components/form-control/field/TextInput.tsx +7 -4
  149. package/src/components/form-control/field/Textarea.tsx +6 -3
  150. package/src/components/form-control/field/TimePicker.tsx +6 -3
  151. package/src/components/form-control/numpad/Numpad.tsx +3 -1
  152. package/src/components/form-control/select/Select.tsx +7 -7
  153. package/src/components/form-control/state-preset/StatePreset.tsx +14 -12
  154. package/src/components/layout/sidebar/SidebarContainer.tsx +3 -3
  155. package/src/components/layout/sidebar/SidebarMenu.tsx +3 -1
  156. package/src/components/layout/topbar/Topbar.tsx +3 -3
  157. package/src/components/layout/topbar/TopbarMenu.tsx +3 -3
  158. package/src/hooks/createSelectionGroup.tsx +8 -4
  159. package/src/providers/i18n/I18nContext.tsx +0 -7
  160. package/src/providers/i18n/locales/en.ts +38 -0
  161. package/src/providers/i18n/locales/ko.ts +38 -0
  162. package/tailwind.config.ts +2 -2
  163. package/tests/components/data/kanban/Kanban.selection.spec.tsx +34 -24
  164. package/tests/components/disclosure/Dialog.spec.tsx +28 -28
  165. package/tests/components/disclosure/DialogProvider.spec.tsx +51 -25
  166. package/tests/components/features/address/AddressSearch.spec.tsx +12 -4
  167. package/tests/components/features/crud-detail/CrudDetail.spec.tsx +1 -0
  168. package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +30 -6
  169. package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +77 -56
  170. package/tests/components/features/permission-table/PermissionTable.spec.tsx +12 -8
  171. package/tests/components/features/shared-data/SharedDataSelect.spec.tsx +172 -0
  172. package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +14 -2
  173. package/tests/components/feedback/notification/LiveRegion.spec.tsx +20 -9
  174. package/tests/components/feedback/notification/NotificationBanner.spec.tsx +64 -46
  175. package/tests/components/feedback/notification/NotificationBell.spec.tsx +70 -51
  176. package/tests/components/feedback/notification/NotificationContext.spec.tsx +105 -78
  177. package/tests/components/form-control/checkbox/Checkbox.spec.tsx +25 -20
  178. package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +53 -30
  179. package/tests/components/form-control/checkbox/Radio.spec.tsx +25 -20
  180. package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +53 -30
  181. package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +24 -15
  182. package/tests/components/form-control/combobox/Combobox.spec.tsx +92 -59
  183. package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +2 -2
  184. package/tests/components/form-control/field/DatePicker.spec.tsx +50 -44
  185. package/tests/components/form-control/field/DateTimePicker.spec.tsx +51 -45
  186. package/tests/components/form-control/field/NumberInput.spec.tsx +53 -47
  187. package/tests/components/form-control/field/TextInput.spec.tsx +50 -44
  188. package/tests/components/form-control/field/Textarea.spec.tsx +35 -29
  189. package/tests/components/form-control/field/TimePicker.spec.tsx +43 -37
  190. package/tests/components/form-control/numpad/Numpad.spec.tsx +175 -25
  191. package/tests/components/form-control/select/Select.spec.tsx +5 -0
  192. package/tests/components/form-control/select/SelectItem.spec.tsx +1 -0
  193. package/tests/components/layout/sidebar/Sidebar.spec.tsx +79 -35
  194. package/tests/components/layout/sidebar/SidebarContainer.spec.tsx +1 -0
  195. package/tests/components/layout/sidebar/SidebarMenu.spec.tsx +28 -17
  196. package/tests/components/layout/topbar/TopbarActions.spec.tsx +41 -23
  197. package/tests/components/layout/topbar/createTopbarActions.spec.tsx +1 -0
  198. package/tests/hooks/usePrint.spec.tsx +1 -1
  199. package/tests/hooks/useRouterLink.spec.tsx +2 -0
  200. package/tests/hooks/useSyncConfig.spec.tsx +1 -0
  201. package/tests/providers/ErrorLoggerProvider.spec.tsx +1 -0
  202. package/tests/providers/PwaUpdateProvider.spec.tsx +16 -6
  203. package/tests/providers/ServiceClientContext.spec.tsx +40 -25
  204. package/tests/providers/i18n/I18nContext.spec.tsx +3 -4
  205. package/tests/providers/shared-data/SharedDataProvider.spec.tsx +2 -0
  206. package/dist/hooks/usePrint.d.ts +0 -3
  207. package/dist/hooks/usePrint.d.ts.map +0 -1
  208. package/dist/hooks/usePrint.js +0 -5
  209. package/dist/hooks/usePrint.js.map +0 -6
  210. package/src/hooks/usePrint.ts +0 -2
@@ -1,33 +1,39 @@
1
- import { describe, it, expect, vi } from "vitest";
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
2
  import { render, fireEvent, screen } from "@solidjs/testing-library";
3
3
  import { createSignal } from "solid-js";
4
4
  import { NumberInput } from "../../../../src/components/form-control/field/NumberInput";
5
+ import { I18nProvider } from "../../../../src/providers/i18n/I18nContext";
6
+ import { ConfigProvider } from "../../../../src/providers/ConfigContext";
5
7
 
6
8
  describe("NumberInput", () => {
9
+ beforeEach(() => {
10
+ localStorage.setItem("test.i18n-locale", JSON.stringify("en"));
11
+ });
12
+
7
13
  describe("basic rendering", () => {
8
14
  it("renders input element", () => {
9
- render(() => <NumberInput />);
15
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput /></I18nProvider></ConfigProvider>);
10
16
 
11
17
  const input = screen.getByRole("textbox");
12
18
  expect(input).toBeInTheDocument();
13
19
  });
14
20
 
15
21
  it("sets inputmode to numeric", () => {
16
- render(() => <NumberInput />);
22
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput /></I18nProvider></ConfigProvider>);
17
23
 
18
24
  const input = screen.getByRole("textbox");
19
25
  expect(input).toHaveAttribute("inputmode", "numeric");
20
26
  });
21
27
 
22
28
  it("sets input type to text", () => {
23
- render(() => <NumberInput />);
29
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput /></I18nProvider></ConfigProvider>);
24
30
 
25
31
  const input = screen.getByRole("textbox");
26
32
  expect(input).toHaveAttribute("type", "text");
27
33
  });
28
34
 
29
35
  it("defaults autocomplete to one-time-code", () => {
30
- render(() => <NumberInput />);
36
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput /></I18nProvider></ConfigProvider>);
31
37
 
32
38
  const input = screen.getByRole("textbox");
33
39
  expect(input).toHaveAttribute("autocomplete", "one-time-code");
@@ -36,7 +42,7 @@ describe("NumberInput", () => {
36
42
 
37
43
  describe("value conversion", () => {
38
44
  it("displays numeric value as string", () => {
39
- render(() => <NumberInput value={12345} />);
45
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={12345} /></I18nProvider></ConfigProvider>);
40
46
 
41
47
  const input = screen.getByRole("textbox");
42
48
  // comma is true by default, so commas are included
@@ -44,7 +50,7 @@ describe("NumberInput", () => {
44
50
  });
45
51
 
46
52
  it("displays decimal numbers correctly", () => {
47
- render(() => <NumberInput value={1234.56} />);
53
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={1234.56} /></I18nProvider></ConfigProvider>);
48
54
 
49
55
  const input = screen.getByRole("textbox");
50
56
  expect(input).toHaveValue("1,234.56");
@@ -52,7 +58,7 @@ describe("NumberInput", () => {
52
58
 
53
59
  it("works correctly during input", () => {
54
60
  const handleChange = vi.fn();
55
- render(() => <NumberInput onValueChange={handleChange} />);
61
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput onValueChange={handleChange} /></I18nProvider></ConfigProvider>);
56
62
 
57
63
  const input = screen.getByRole("textbox");
58
64
  fireEvent.input(input, { target: { value: "123" } });
@@ -62,7 +68,7 @@ describe("NumberInput", () => {
62
68
 
63
69
  it("preserves trailing decimal point during input", () => {
64
70
  const [value, setValue] = createSignal<number | undefined>(undefined);
65
- render(() => <NumberInput value={value()} onValueChange={setValue} />);
71
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={value()} onValueChange={setValue} /></I18nProvider></ConfigProvider>);
66
72
 
67
73
  const input = screen.getByRole("textbox");
68
74
 
@@ -75,7 +81,7 @@ describe("NumberInput", () => {
75
81
 
76
82
  it("ignores invalid input", () => {
77
83
  const handleChange = vi.fn();
78
- render(() => <NumberInput value={100} onValueChange={handleChange} />);
84
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={100} onValueChange={handleChange} /></I18nProvider></ConfigProvider>);
79
85
 
80
86
  const input = screen.getByRole("textbox");
81
87
  // attempt to input non-numeric characters
@@ -87,7 +93,7 @@ describe("NumberInput", () => {
87
93
 
88
94
  it("converts empty input to undefined", () => {
89
95
  const handleChange = vi.fn();
90
- render(() => <NumberInput value={100} onValueChange={handleChange} />);
96
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={100} onValueChange={handleChange} /></I18nProvider></ConfigProvider>);
91
97
 
92
98
  const input = screen.getByRole("textbox");
93
99
  fireEvent.input(input, { target: { value: "" } });
@@ -97,7 +103,7 @@ describe("NumberInput", () => {
97
103
 
98
104
  it("handles negative numbers correctly", () => {
99
105
  const handleChange = vi.fn();
100
- render(() => <NumberInput onValueChange={handleChange} />);
106
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput onValueChange={handleChange} /></I18nProvider></ConfigProvider>);
101
107
 
102
108
  const input = screen.getByRole("textbox");
103
109
  fireEvent.input(input, { target: { value: "-123" } });
@@ -108,35 +114,35 @@ describe("NumberInput", () => {
108
114
 
109
115
  describe("display format", () => {
110
116
  it("displays thousands comma when comma=true", () => {
111
- render(() => <NumberInput value={1234567} comma={true} />);
117
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={1234567} comma={true} /></I18nProvider></ConfigProvider>);
112
118
 
113
119
  const input = screen.getByRole("textbox");
114
120
  expect(input).toHaveValue("1,234,567");
115
121
  });
116
122
 
117
123
  it("displays without comma when comma=false", () => {
118
- render(() => <NumberInput value={1234567} comma={false} />);
124
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={1234567} comma={false} /></I18nProvider></ConfigProvider>);
119
125
 
120
126
  const input = screen.getByRole("textbox");
121
127
  expect(input).toHaveValue("1234567");
122
128
  });
123
129
 
124
130
  it("defaults comma to true", () => {
125
- render(() => <NumberInput value={1234567} />);
131
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={1234567} /></I18nProvider></ConfigProvider>);
126
132
 
127
133
  const input = screen.getByRole("textbox");
128
134
  expect(input).toHaveValue("1,234,567");
129
135
  });
130
136
 
131
137
  it("sets minimum decimal digits with minDigits", () => {
132
- render(() => <NumberInput value={100} minDigits={2} />);
138
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={100} minDigits={2} /></I18nProvider></ConfigProvider>);
133
139
 
134
140
  const input = screen.getByRole("textbox");
135
141
  expect(input).toHaveValue("100.00");
136
142
  });
137
143
 
138
144
  it("displays decimals longer than minDigits as-is", () => {
139
- render(() => <NumberInput value={100.12345} minDigits={2} />);
145
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={100.12345} minDigits={2} /></I18nProvider></ConfigProvider>);
140
146
 
141
147
  const input = screen.getByRole("textbox");
142
148
  expect(input).toHaveValue("100.12345");
@@ -145,7 +151,7 @@ describe("NumberInput", () => {
145
151
 
146
152
  describe("disabled/readonly state", () => {
147
153
  it("renders as div when disabled", () => {
148
- render(() => <NumberInput value={1234} disabled />);
154
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={1234} disabled /></I18nProvider></ConfigProvider>);
149
155
 
150
156
  // renders as div, not input, when disabled
151
157
  expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
@@ -154,14 +160,14 @@ describe("NumberInput", () => {
154
160
  });
155
161
 
156
162
  it("renders as div when readonly", () => {
157
- render(() => <NumberInput value={5678} readonly />);
163
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={5678} readonly /></I18nProvider></ConfigProvider>);
158
164
 
159
165
  expect(screen.queryByRole("textbox")).not.toBeInTheDocument();
160
166
  expect(screen.getByText("5,678")).toBeInTheDocument();
161
167
  });
162
168
 
163
169
  it("applies disabled style", () => {
164
- const { container } = render(() => <NumberInput value={100} disabled />);
170
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={100} disabled /></I18nProvider></ConfigProvider>);
165
171
 
166
172
  const wrapper = container.firstChild as HTMLElement;
167
173
  expect(wrapper.className).toContain("bg-base-100");
@@ -170,7 +176,7 @@ describe("NumberInput", () => {
170
176
 
171
177
  describe("right alignment", () => {
172
178
  it("aligns input to the right", () => {
173
- render(() => <NumberInput />);
179
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput /></I18nProvider></ConfigProvider>);
174
180
 
175
181
  const input = screen.getByRole("textbox");
176
182
  expect(input.className).toContain("text-right");
@@ -179,21 +185,21 @@ describe("NumberInput", () => {
179
185
 
180
186
  describe("style options", () => {
181
187
  it("applies small padding when size='sm'", () => {
182
- const { container } = render(() => <NumberInput size="sm" />);
188
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput size="sm" /></I18nProvider></ConfigProvider>);
183
189
 
184
190
  const wrapper = container.firstChild as HTMLElement;
185
191
  expect(wrapper.className).toContain("px-1.5");
186
192
  });
187
193
 
188
194
  it("applies large padding when size='lg'", () => {
189
- const { container } = render(() => <NumberInput size="lg" />);
195
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput size="lg" /></I18nProvider></ConfigProvider>);
190
196
 
191
197
  const wrapper = container.firstChild as HTMLElement;
192
198
  expect(wrapper.className).toContain("px-3");
193
199
  });
194
200
 
195
201
  it("applies inset style", () => {
196
- const { container } = render(() => <NumberInput inset />);
202
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput inset /></I18nProvider></ConfigProvider>);
197
203
 
198
204
  // outer div is relative when inset, inner content div has border-none
199
205
  const outer = container.firstChild as HTMLElement;
@@ -205,7 +211,7 @@ describe("NumberInput", () => {
205
211
 
206
212
  describe("inset dual-element", () => {
207
213
  it("shows content div and no input when inset + readonly", () => {
208
- const { container } = render(() => <NumberInput inset readonly value={1234} />);
214
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput inset readonly value={1234} /></I18nProvider></ConfigProvider>);
209
215
  const outer = container.firstChild as HTMLElement;
210
216
  expect(outer.classList.contains("relative")).toBe(true);
211
217
 
@@ -217,7 +223,7 @@ describe("NumberInput", () => {
217
223
  });
218
224
 
219
225
  it("shows hidden content div and input when inset + editable", () => {
220
- const { container } = render(() => <NumberInput inset value={1234} />);
226
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput inset value={1234} /></I18nProvider></ConfigProvider>);
221
227
  const outer = container.firstChild as HTMLElement;
222
228
 
223
229
  const contentDiv = outer.querySelector("[data-number-field-content]") as HTMLElement;
@@ -229,14 +235,14 @@ describe("NumberInput", () => {
229
235
  });
230
236
 
231
237
  it("applies right alignment in inset + readonly", () => {
232
- const { container } = render(() => <NumberInput inset readonly value={100} />);
238
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput inset readonly value={100} /></I18nProvider></ConfigProvider>);
233
239
  const outer = container.firstChild as HTMLElement;
234
240
  const contentDiv = outer.querySelector("[data-number-field-content]") as HTMLElement;
235
241
  expect(contentDiv.classList.contains("justify-end")).toBe(true);
236
242
  });
237
243
 
238
244
  it("shows NBSP in content div when inset + empty value", () => {
239
- const { container } = render(() => <NumberInput inset readonly />);
245
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput inset readonly /></I18nProvider></ConfigProvider>);
240
246
  const outer = container.firstChild as HTMLElement;
241
247
  const contentDiv = outer.querySelector("[data-number-field-content]") as HTMLElement;
242
248
  expect(contentDiv.textContent).toBe("\u00A0");
@@ -246,7 +252,7 @@ describe("NumberInput", () => {
246
252
  describe("controlled/uncontrolled pattern", () => {
247
253
  it("reflects external value changes in controlled mode", () => {
248
254
  const [value, setValue] = createSignal<number | undefined>(100);
249
- render(() => <NumberInput value={value()} onValueChange={setValue} />);
255
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput value={value()} onValueChange={setValue} /></I18nProvider></ConfigProvider>);
250
256
 
251
257
  const input = screen.getByRole("textbox");
252
258
  expect(input).toHaveValue("100");
@@ -256,7 +262,7 @@ describe("NumberInput", () => {
256
262
  });
257
263
 
258
264
  it("manages internal state in uncontrolled mode", () => {
259
- render(() => <NumberInput />);
265
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput /></I18nProvider></ConfigProvider>);
260
266
 
261
267
  const input = screen.getByRole("textbox");
262
268
  fireEvent.input(input, { target: { value: "500" } });
@@ -267,7 +273,7 @@ describe("NumberInput", () => {
267
273
 
268
274
  describe("placeholder", () => {
269
275
  it("displays placeholder", () => {
270
- render(() => <NumberInput placeholder="숫자를 입력하세요" />);
276
+ render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput placeholder="숫자를 입력하세요" /></I18nProvider></ConfigProvider>);
271
277
 
272
278
  const input = screen.getByRole("textbox");
273
279
  expect(input).toHaveAttribute("placeholder", "숫자를 입력하세요");
@@ -276,35 +282,35 @@ describe("NumberInput", () => {
276
282
 
277
283
  describe("validation", () => {
278
284
  it("sets error message when required and value is empty", () => {
279
- const { container } = render(() => <NumberInput required value={undefined} />);
285
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput required value={undefined} /></I18nProvider></ConfigProvider>);
280
286
  const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
281
- expect(hiddenInput.validationMessage).toBe("This field is required");
287
+ expect(hiddenInput.validationMessage).toBe("This is a required field");
282
288
  });
283
289
 
284
290
  it("is valid when required and value exists", () => {
285
- const { container } = render(() => <NumberInput required value={42} />);
291
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput required value={42} /></I18nProvider></ConfigProvider>);
286
292
  const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
287
293
  expect(hiddenInput.validity.valid).toBe(true);
288
294
  });
289
295
 
290
296
  it("sets error message when min is violated", () => {
291
- const { container } = render(() => <NumberInput min={10} value={5} />);
297
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput min={10} value={5} /></I18nProvider></ConfigProvider>);
292
298
  const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
293
299
  expect(hiddenInput.validationMessage).toBe("Minimum value is 10");
294
300
  });
295
301
 
296
302
  it("sets error message when max is violated", () => {
297
- const { container } = render(() => <NumberInput max={100} value={150} />);
303
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput max={100} value={150} /></I18nProvider></ConfigProvider>);
298
304
  const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
299
305
  expect(hiddenInput.validationMessage).toBe("Maximum value is 100");
300
306
  });
301
307
 
302
308
  it("sets error message returned by validate function", () => {
303
309
  const { container } = render(() => (
304
- <NumberInput
310
+ <ConfigProvider clientName="test"><I18nProvider><NumberInput
305
311
  validate={(v) => (v !== undefined && v % 2 === 0 ? undefined : "짝수만 입력하세요")}
306
312
  value={3}
307
- />
313
+ /></I18nProvider></ConfigProvider>
308
314
  ));
309
315
  const hiddenInput = container.querySelector("input[aria-hidden='true']") as HTMLInputElement;
310
316
  expect(hiddenInput.validationMessage).toBe("짝수만 입력하세요");
@@ -314,11 +320,11 @@ describe("NumberInput", () => {
314
320
  describe("Prefix slot", () => {
315
321
  it("renders NumberInput.Prefix slot", () => {
316
322
  render(() => (
317
- <NumberInput>
323
+ <ConfigProvider clientName="test"><I18nProvider><NumberInput>
318
324
  <NumberInput.Prefix>
319
325
  <span data-testid="prefix">₩</span>
320
326
  </NumberInput.Prefix>
321
- </NumberInput>
327
+ </NumberInput></I18nProvider></ConfigProvider>
322
328
  ));
323
329
 
324
330
  expect(document.querySelector('[data-testid="prefix"]')).not.toBeNull();
@@ -326,11 +332,11 @@ describe("NumberInput", () => {
326
332
 
327
333
  it("applies gap class when Prefix slot is used", () => {
328
334
  const { container } = render(() => (
329
- <NumberInput>
335
+ <ConfigProvider clientName="test"><I18nProvider><NumberInput>
330
336
  <NumberInput.Prefix>
331
337
  <span>₩</span>
332
338
  </NumberInput.Prefix>
333
- </NumberInput>
339
+ </NumberInput></I18nProvider></ConfigProvider>
334
340
  ));
335
341
 
336
342
  const wrapper = container.querySelector("[data-number-field]") as HTMLElement;
@@ -338,7 +344,7 @@ describe("NumberInput", () => {
338
344
  });
339
345
 
340
346
  it("does not apply gap class without Prefix slot", () => {
341
- const { container } = render(() => <NumberInput />);
347
+ const { container } = render(() => <ConfigProvider clientName="test"><I18nProvider><NumberInput /></I18nProvider></ConfigProvider>);
342
348
 
343
349
  const wrapper = container.querySelector("[data-number-field]") as HTMLElement;
344
350
  expect(wrapper.className).not.toContain("gap-");
@@ -346,11 +352,11 @@ describe("NumberInput", () => {
346
352
 
347
353
  it("renders Prefix slot when disabled", () => {
348
354
  render(() => (
349
- <NumberInput disabled value={100}>
355
+ <ConfigProvider clientName="test"><I18nProvider><NumberInput disabled value={100}>
350
356
  <NumberInput.Prefix>
351
357
  <span data-testid="prefix">₩</span>
352
358
  </NumberInput.Prefix>
353
- </NumberInput>
359
+ </NumberInput></I18nProvider></ConfigProvider>
354
360
  ));
355
361
 
356
362
  expect(document.querySelector('[data-testid="prefix"]')).not.toBeNull();
@@ -358,11 +364,11 @@ describe("NumberInput", () => {
358
364
 
359
365
  it("renders Prefix slot in inset mode", () => {
360
366
  render(() => (
361
- <NumberInput inset value={100}>
367
+ <ConfigProvider clientName="test"><I18nProvider><NumberInput inset value={100}>
362
368
  <NumberInput.Prefix>
363
369
  <span data-testid="prefix">₩</span>
364
370
  </NumberInput.Prefix>
365
- </NumberInput>
371
+ </NumberInput></I18nProvider></ConfigProvider>
366
372
  ));
367
373
 
368
374
  expect(document.querySelector('[data-testid="prefix"]')).not.toBeNull();