@simplysm/solid 13.0.71 → 13.0.74

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 (215) 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.d.ts.map +1 -1
  6. package/dist/components/data/sheet/DataSheet.js +13 -16
  7. package/dist/components/data/sheet/DataSheet.js.map +2 -2
  8. package/dist/components/data/sheet/DataSheet.styles.d.ts.map +1 -1
  9. package/dist/components/data/sheet/DataSheet.styles.js +1 -1
  10. package/dist/components/data/sheet/DataSheet.styles.js.map +1 -1
  11. package/dist/components/data/sheet/DataSheetConfigDialog.d.ts.map +1 -1
  12. package/dist/components/data/sheet/DataSheetConfigDialog.js +27 -9
  13. package/dist/components/data/sheet/DataSheetConfigDialog.js.map +2 -2
  14. package/dist/components/disclosure/Dialog.d.ts +1 -1
  15. package/dist/components/disclosure/Dialog.d.ts.map +1 -1
  16. package/dist/components/disclosure/Dialog.js +5 -5
  17. package/dist/components/disclosure/Dialog.js.map +2 -2
  18. package/dist/components/disclosure/dialogZIndex.d.ts +1 -1
  19. package/dist/components/features/crud-detail/CrudDetail.js +23 -23
  20. package/dist/components/features/crud-detail/CrudDetail.js.map +2 -2
  21. package/dist/components/features/crud-sheet/CrudSheet.js +49 -49
  22. package/dist/components/features/crud-sheet/CrudSheet.js.map +2 -2
  23. package/dist/components/features/crud-sheet/types.d.ts +4 -4
  24. package/dist/components/features/crud-sheet/types.d.ts.map +1 -1
  25. package/dist/components/features/data-select-button/DataSelectButton.d.ts +25 -7
  26. package/dist/components/features/data-select-button/DataSelectButton.d.ts.map +1 -1
  27. package/dist/components/features/data-select-button/DataSelectButton.js +27 -12
  28. package/dist/components/features/data-select-button/DataSelectButton.js.map +2 -2
  29. package/dist/components/features/permission-table/PermissionTable.js +4 -4
  30. package/dist/components/features/permission-table/PermissionTable.js.map +2 -2
  31. package/dist/components/features/shared-data/SharedDataSelect.d.ts +22 -10
  32. package/dist/components/features/shared-data/SharedDataSelect.d.ts.map +1 -1
  33. package/dist/components/features/shared-data/SharedDataSelect.js +113 -29
  34. package/dist/components/features/shared-data/SharedDataSelect.js.map +2 -2
  35. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts +3 -3
  36. package/dist/components/features/shared-data/SharedDataSelectButton.d.ts.map +1 -1
  37. package/dist/components/features/shared-data/SharedDataSelectButton.js.map +1 -1
  38. package/dist/components/features/shared-data/SharedDataSelectList.js +5 -4
  39. package/dist/components/features/shared-data/SharedDataSelectList.js.map +2 -2
  40. package/dist/components/feedback/notification/NotificationBanner.js +3 -3
  41. package/dist/components/feedback/notification/NotificationBanner.js.map +2 -2
  42. package/dist/components/feedback/notification/NotificationBell.d.ts.map +1 -1
  43. package/dist/components/feedback/notification/NotificationBell.js +12 -5
  44. package/dist/components/feedback/notification/NotificationBell.js.map +2 -2
  45. package/dist/components/feedback/notification/NotificationProvider.d.ts.map +1 -1
  46. package/dist/components/feedback/notification/NotificationProvider.js +3 -1
  47. package/dist/components/feedback/notification/NotificationProvider.js.map +2 -2
  48. package/dist/components/form-control/ThemeToggle.d.ts.map +1 -1
  49. package/dist/components/form-control/ThemeToggle.js +9 -6
  50. package/dist/components/form-control/ThemeToggle.js.map +2 -2
  51. package/dist/components/form-control/checkbox/Checkbox.d.ts.map +1 -1
  52. package/dist/components/form-control/checkbox/Checkbox.js +3 -1
  53. package/dist/components/form-control/checkbox/Checkbox.js.map +2 -2
  54. package/dist/components/form-control/checkbox/CheckboxGroup.js +1 -1
  55. package/dist/components/form-control/checkbox/CheckboxGroup.js.map +2 -2
  56. package/dist/components/form-control/checkbox/Radio.d.ts.map +1 -1
  57. package/dist/components/form-control/checkbox/Radio.js +3 -1
  58. package/dist/components/form-control/checkbox/Radio.js.map +2 -2
  59. package/dist/components/form-control/checkbox/RadioGroup.js +1 -1
  60. package/dist/components/form-control/checkbox/RadioGroup.js.map +2 -2
  61. package/dist/components/form-control/color-picker/ColorPicker.d.ts.map +1 -1
  62. package/dist/components/form-control/color-picker/ColorPicker.js +3 -1
  63. package/dist/components/form-control/color-picker/ColorPicker.js.map +2 -2
  64. package/dist/components/form-control/combobox/Combobox.d.ts.map +1 -1
  65. package/dist/components/form-control/combobox/Combobox.js +9 -5
  66. package/dist/components/form-control/combobox/Combobox.js.map +2 -2
  67. package/dist/components/form-control/date-range-picker/DateRangePicker.js +9 -9
  68. package/dist/components/form-control/date-range-picker/DateRangePicker.js.map +2 -2
  69. package/dist/components/form-control/editor/EditorToolbar.js +3 -3
  70. package/dist/components/form-control/editor/EditorToolbar.js.map +2 -2
  71. package/dist/components/form-control/field/DatePicker.d.ts.map +1 -1
  72. package/dist/components/form-control/field/DatePicker.js +9 -3
  73. package/dist/components/form-control/field/DatePicker.js.map +2 -2
  74. package/dist/components/form-control/field/DateTimePicker.d.ts.map +1 -1
  75. package/dist/components/form-control/field/DateTimePicker.js +9 -3
  76. package/dist/components/form-control/field/DateTimePicker.js.map +2 -2
  77. package/dist/components/form-control/field/NumberInput.d.ts.map +1 -1
  78. package/dist/components/form-control/field/NumberInput.js +9 -3
  79. package/dist/components/form-control/field/NumberInput.js.map +2 -2
  80. package/dist/components/form-control/field/TextInput.d.ts.map +1 -1
  81. package/dist/components/form-control/field/TextInput.js +10 -4
  82. package/dist/components/form-control/field/TextInput.js.map +2 -2
  83. package/dist/components/form-control/field/Textarea.d.ts.map +1 -1
  84. package/dist/components/form-control/field/Textarea.js +9 -3
  85. package/dist/components/form-control/field/Textarea.js.map +2 -2
  86. package/dist/components/form-control/field/TimePicker.d.ts.map +1 -1
  87. package/dist/components/form-control/field/TimePicker.js +9 -3
  88. package/dist/components/form-control/field/TimePicker.js.map +2 -2
  89. package/dist/components/form-control/numpad/Numpad.d.ts.map +1 -1
  90. package/dist/components/form-control/numpad/Numpad.js +5 -1
  91. package/dist/components/form-control/numpad/Numpad.js.map +2 -2
  92. package/dist/components/form-control/select/Select.js +7 -7
  93. package/dist/components/form-control/select/Select.js.map +2 -2
  94. package/dist/components/form-control/state-preset/StatePreset.d.ts.map +1 -1
  95. package/dist/components/form-control/state-preset/StatePreset.js +42 -20
  96. package/dist/components/form-control/state-preset/StatePreset.js.map +2 -2
  97. package/dist/components/layout/sidebar/SidebarContainer.js +3 -3
  98. package/dist/components/layout/sidebar/SidebarContainer.js.map +2 -2
  99. package/dist/components/layout/sidebar/SidebarMenu.d.ts.map +1 -1
  100. package/dist/components/layout/sidebar/SidebarMenu.js +5 -2
  101. package/dist/components/layout/sidebar/SidebarMenu.js.map +2 -2
  102. package/dist/components/layout/topbar/Topbar.js +3 -4
  103. package/dist/components/layout/topbar/Topbar.js.map +2 -2
  104. package/dist/components/layout/topbar/TopbarMenu.js +3 -3
  105. package/dist/components/layout/topbar/TopbarMenu.js.map +2 -2
  106. package/dist/hooks/createSelectionGroup.d.ts +2 -2
  107. package/dist/hooks/createSelectionGroup.d.ts.map +1 -1
  108. package/dist/hooks/createSelectionGroup.js +5 -2
  109. package/dist/hooks/createSelectionGroup.js.map +2 -2
  110. package/dist/providers/i18n/I18nContext.d.ts +0 -4
  111. package/dist/providers/i18n/I18nContext.d.ts.map +1 -1
  112. package/dist/providers/i18n/I18nContext.js +1 -5
  113. package/dist/providers/i18n/I18nContext.js.map +2 -2
  114. package/dist/providers/i18n/locales/en.d.ts +38 -0
  115. package/dist/providers/i18n/locales/en.d.ts.map +1 -1
  116. package/dist/providers/i18n/locales/en.js +39 -1
  117. package/dist/providers/i18n/locales/en.js.map +1 -1
  118. package/dist/providers/i18n/locales/ko.d.ts +38 -0
  119. package/dist/providers/i18n/locales/ko.d.ts.map +1 -1
  120. package/dist/providers/i18n/locales/ko.js +39 -1
  121. package/dist/providers/i18n/locales/ko.js.map +1 -1
  122. package/package.json +6 -6
  123. package/src/components/data/calendar/Calendar.tsx +3 -4
  124. package/src/components/data/sheet/DataSheet.styles.ts +1 -1
  125. package/src/components/data/sheet/DataSheet.tsx +14 -15
  126. package/src/components/data/sheet/DataSheetConfigDialog.tsx +12 -10
  127. package/src/components/data/sheet/types.ts +1 -1
  128. package/src/components/disclosure/Dialog.tsx +10 -10
  129. package/src/components/disclosure/dialogZIndex.ts +1 -1
  130. package/src/components/features/crud-detail/CrudDetail.tsx +25 -25
  131. package/src/components/features/crud-sheet/CrudSheet.tsx +53 -53
  132. package/src/components/features/crud-sheet/types.ts +4 -4
  133. package/src/components/features/data-select-button/DataSelectButton.tsx +51 -21
  134. package/src/components/features/permission-table/PermissionTable.tsx +3 -3
  135. package/src/components/features/shared-data/SharedDataSelect.tsx +172 -33
  136. package/src/components/features/shared-data/SharedDataSelectButton.tsx +3 -2
  137. package/src/components/features/shared-data/SharedDataSelectList.tsx +4 -4
  138. package/src/components/feedback/notification/NotificationBanner.tsx +3 -3
  139. package/src/components/feedback/notification/NotificationBell.tsx +6 -4
  140. package/src/components/feedback/notification/NotificationProvider.tsx +3 -1
  141. package/src/components/form-control/ThemeToggle.tsx +10 -6
  142. package/src/components/form-control/checkbox/Checkbox.tsx +4 -1
  143. package/src/components/form-control/checkbox/CheckboxGroup.tsx +1 -1
  144. package/src/components/form-control/checkbox/Radio.tsx +4 -1
  145. package/src/components/form-control/checkbox/RadioGroup.tsx +1 -1
  146. package/src/components/form-control/color-picker/ColorPicker.tsx +4 -1
  147. package/src/components/form-control/combobox/Combobox.tsx +6 -3
  148. package/src/components/form-control/date-range-picker/DateRangePicker.tsx +8 -8
  149. package/src/components/form-control/editor/EditorToolbar.tsx +23 -23
  150. package/src/components/form-control/field/DatePicker.tsx +6 -3
  151. package/src/components/form-control/field/DateTimePicker.tsx +6 -3
  152. package/src/components/form-control/field/NumberInput.tsx +6 -3
  153. package/src/components/form-control/field/TextInput.tsx +7 -4
  154. package/src/components/form-control/field/Textarea.tsx +6 -3
  155. package/src/components/form-control/field/TimePicker.tsx +6 -3
  156. package/src/components/form-control/numpad/Numpad.tsx +3 -1
  157. package/src/components/form-control/select/Select.tsx +7 -7
  158. package/src/components/form-control/state-preset/StatePreset.tsx +14 -12
  159. package/src/components/layout/sidebar/SidebarContainer.tsx +3 -3
  160. package/src/components/layout/sidebar/SidebarMenu.tsx +3 -1
  161. package/src/components/layout/topbar/Topbar.tsx +3 -3
  162. package/src/components/layout/topbar/TopbarMenu.tsx +3 -3
  163. package/src/hooks/createSelectionGroup.tsx +8 -4
  164. package/src/providers/i18n/I18nContext.tsx +0 -7
  165. package/src/providers/i18n/locales/en.ts +38 -0
  166. package/src/providers/i18n/locales/ko.ts +38 -0
  167. package/tailwind.config.ts +2 -2
  168. package/tests/components/data/kanban/Kanban.selection.spec.tsx +34 -24
  169. package/tests/components/disclosure/Dialog.spec.tsx +28 -28
  170. package/tests/components/disclosure/DialogProvider.spec.tsx +51 -25
  171. package/tests/components/features/address/AddressSearch.spec.tsx +12 -4
  172. package/tests/components/features/crud-detail/CrudDetail.spec.tsx +1 -0
  173. package/tests/components/features/crud-sheet/CrudSheet.spec.tsx +30 -6
  174. package/tests/components/features/data-select-button/DataSelectButton.spec.tsx +77 -56
  175. package/tests/components/features/permission-table/PermissionTable.spec.tsx +12 -8
  176. package/tests/components/features/shared-data/SharedDataSelect.spec.tsx +172 -0
  177. package/tests/components/features/shared-data/SharedDataSelectList.spec.tsx +14 -2
  178. package/tests/components/feedback/notification/LiveRegion.spec.tsx +20 -9
  179. package/tests/components/feedback/notification/NotificationBanner.spec.tsx +64 -46
  180. package/tests/components/feedback/notification/NotificationBell.spec.tsx +70 -51
  181. package/tests/components/feedback/notification/NotificationContext.spec.tsx +105 -78
  182. package/tests/components/form-control/checkbox/Checkbox.spec.tsx +25 -20
  183. package/tests/components/form-control/checkbox/CheckboxGroup.spec.tsx +53 -30
  184. package/tests/components/form-control/checkbox/Radio.spec.tsx +25 -20
  185. package/tests/components/form-control/checkbox/RadioGroup.spec.tsx +53 -30
  186. package/tests/components/form-control/color-picker/ColorPicker.spec.tsx +24 -15
  187. package/tests/components/form-control/combobox/Combobox.spec.tsx +92 -59
  188. package/tests/components/form-control/date-range-picker/DateRangePicker.spec.tsx +2 -2
  189. package/tests/components/form-control/field/DatePicker.spec.tsx +50 -44
  190. package/tests/components/form-control/field/DateTimePicker.spec.tsx +51 -45
  191. package/tests/components/form-control/field/NumberInput.spec.tsx +53 -47
  192. package/tests/components/form-control/field/TextInput.spec.tsx +50 -44
  193. package/tests/components/form-control/field/Textarea.spec.tsx +35 -29
  194. package/tests/components/form-control/field/TimePicker.spec.tsx +43 -37
  195. package/tests/components/form-control/numpad/Numpad.spec.tsx +175 -25
  196. package/tests/components/form-control/select/Select.spec.tsx +5 -0
  197. package/tests/components/form-control/select/SelectItem.spec.tsx +1 -0
  198. package/tests/components/layout/sidebar/Sidebar.spec.tsx +79 -35
  199. package/tests/components/layout/sidebar/SidebarContainer.spec.tsx +1 -0
  200. package/tests/components/layout/sidebar/SidebarMenu.spec.tsx +28 -17
  201. package/tests/components/layout/topbar/TopbarActions.spec.tsx +41 -23
  202. package/tests/components/layout/topbar/createTopbarActions.spec.tsx +1 -0
  203. package/tests/hooks/usePrint.spec.tsx +1 -1
  204. package/tests/hooks/useRouterLink.spec.tsx +2 -0
  205. package/tests/hooks/useSyncConfig.spec.tsx +1 -0
  206. package/tests/providers/ErrorLoggerProvider.spec.tsx +1 -0
  207. package/tests/providers/PwaUpdateProvider.spec.tsx +16 -6
  208. package/tests/providers/ServiceClientContext.spec.tsx +40 -25
  209. package/tests/providers/i18n/I18nContext.spec.tsx +3 -4
  210. package/tests/providers/shared-data/SharedDataProvider.spec.tsx +2 -0
  211. package/dist/hooks/usePrint.d.ts +0 -3
  212. package/dist/hooks/usePrint.d.ts.map +0 -1
  213. package/dist/hooks/usePrint.js +0 -5
  214. package/dist/hooks/usePrint.js.map +0 -6
  215. package/src/hooks/usePrint.ts +0 -2
@@ -31,7 +31,7 @@ const { Group } = createSelectionGroup({
31
31
  mode: "multiple",
32
32
  contextName: "CheckboxGroup",
33
33
  ItemComponent: Checkbox,
34
- emptyErrorMsg: "Please select an item",
34
+ emptyErrorMsgKey: "validation.selectItem",
35
35
  });
36
36
 
37
37
  export const CheckboxGroup = Group as unknown as CheckboxGroupComponent;
@@ -3,6 +3,7 @@ import { twMerge } from "tailwind-merge";
3
3
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
4
4
  import { ripple } from "../../../directives/ripple";
5
5
  import clsx from "clsx";
6
+ import { useI18n } from "../../../providers/i18n/I18nContext";
6
7
  import {
7
8
  type CheckboxSize,
8
9
  checkboxBaseClass,
@@ -52,6 +53,8 @@ export const Radio: ParentComponent<RadioProps> = (props) => {
52
53
  "children",
53
54
  ]);
54
55
 
56
+ const i18n = useI18n();
57
+
55
58
  const [value, setValue] = createControllableSignal({
56
59
  value: () => local.value ?? false,
57
60
  onChange: () => local.onValueChange,
@@ -85,7 +88,7 @@ export const Radio: ParentComponent<RadioProps> = (props) => {
85
88
 
86
89
  const errorMsg = createMemo(() => {
87
90
  const v = local.value ?? false;
88
- if (local.required && !v) return "This is a required selection";
91
+ if (local.required && !v) return i18n.t("validation.requiredSelection");
89
92
  return local.validate?.(v);
90
93
  });
91
94
 
@@ -31,7 +31,7 @@ const { Group } = createSelectionGroup({
31
31
  mode: "single",
32
32
  contextName: "RadioGroup",
33
33
  ItemComponent: Radio,
34
- emptyErrorMsg: "Please select an item",
34
+ emptyErrorMsgKey: "validation.selectItem",
35
35
  });
36
36
 
37
37
  export const RadioGroup = Group as unknown as RadioGroupComponent;
@@ -4,6 +4,7 @@ import { twMerge } from "tailwind-merge";
4
4
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
5
5
  import { Invalid } from "../Invalid";
6
6
  import { type ComponentSize } from "../../../styles/tokens.styles";
7
+ import { useI18n } from "../../../providers/i18n/I18nContext";
7
8
 
8
9
  // Base style
9
10
  const baseClass = clsx(
@@ -94,6 +95,8 @@ export const ColorPicker: Component<ColorPickerProps> = (props) => {
94
95
  "style",
95
96
  ]);
96
97
 
98
+ const i18n = useI18n();
99
+
97
100
  const [value, setValue] = createControllableSignal({
98
101
  value: () => local.value,
99
102
  onChange: () => local.onValueChange,
@@ -113,7 +116,7 @@ export const ColorPicker: Component<ColorPickerProps> = (props) => {
113
116
 
114
117
  const errorMsg = createMemo(() => {
115
118
  const v = value();
116
- if (local.required && (v === undefined || v === "")) return "This field is required";
119
+ if (local.required && (v === undefined || v === "")) return i18n.t("validation.required");
117
120
  return local.validate?.(v);
118
121
  });
119
122
 
@@ -12,6 +12,7 @@ import { createControllableSignal } from "../../../hooks/createControllableSigna
12
12
  import { type ComponentSize, textMuted } from "../../../styles/tokens.styles";
13
13
  import { chevronWrapperClass, getTriggerClass } from "../DropdownTrigger.styles";
14
14
  import { Invalid } from "../Invalid";
15
+ import { useI18n } from "../../../providers/i18n/I18nContext";
15
16
 
16
17
  void ripple;
17
18
 
@@ -149,6 +150,8 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
149
150
  "touchMode",
150
151
  ]);
151
152
 
153
+ const i18n = useI18n();
154
+
152
155
  // State
153
156
  const [open, setOpen] = createSignal(false);
154
157
  const [query, setQuery] = createSignal("");
@@ -259,7 +262,7 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
259
262
  const errorMsg = createMemo(() => {
260
263
  const v = getValue();
261
264
  if (local.required && (v === undefined || v === null || v === ""))
262
- return "This field is required";
265
+ return i18n.t("validation.required");
263
266
  return local.validate?.(v);
264
267
  });
265
268
 
@@ -310,12 +313,12 @@ export const Combobox: ComboboxComponent = <T,>(props: ComboboxProps<T>) => {
310
313
 
311
314
  // Loading
312
315
  if (busyCount() > 0) {
313
- return <div class={noResultsClass}>Searching...</div>;
316
+ return <div class={noResultsClass}>{i18n.t("combobox.searching")}</div>;
314
317
  }
315
318
 
316
319
  // Items empty
317
320
  if (items().length === 0) {
318
- return <div class={noResultsClass}>No results found</div>;
321
+ return <div class={noResultsClass}>{i18n.t("combobox.noResults")}</div>;
319
322
  }
320
323
 
321
324
  // ItemTemplate approach
@@ -6,7 +6,7 @@ import { createControllableSignal } from "../../../hooks/createControllableSigna
6
6
  import { type FieldSize } from "../field/Field.styles";
7
7
  import { DatePicker } from "../field/DatePicker";
8
8
  import { Select } from "../select/Select";
9
- import { useI18nOptional } from "../../../providers/i18n/I18nContext";
9
+ import { useI18n } from "../../../providers/i18n/I18nContext";
10
10
 
11
11
  export type DateRangePeriodType = "day" | "month" | "range";
12
12
 
@@ -78,7 +78,7 @@ function getLastDayOfMonth(date: DateOnly): DateOnly {
78
78
  * ```
79
79
  */
80
80
  export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
81
- const i18n = useI18nOptional();
81
+ const i18n = useI18n();
82
82
 
83
83
  const [local, rest] = splitProps(props, [
84
84
  "periodType",
@@ -163,9 +163,9 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
163
163
  onValueChange={handlePeriodTypeChange}
164
164
  renderValue={(v: DateRangePeriodType) => {
165
165
  const labels = {
166
- day: i18n?.t("dateRangePicker.day") ?? "Day",
167
- month: i18n?.t("dateRangePicker.month") ?? "Month",
168
- range: i18n?.t("dateRangePicker.range") ?? "Range"
166
+ day: i18n.t("dateRangePicker.day"),
167
+ month: i18n.t("dateRangePicker.month"),
168
+ range: i18n.t("dateRangePicker.range"),
169
169
  };
170
170
  return <>{labels[v]}</>;
171
171
  }}
@@ -175,13 +175,13 @@ export const DateRangePicker: Component<DateRangePickerProps> = (props) => {
175
175
  inset
176
176
  >
177
177
  <Select.Item value={"day" as DateRangePeriodType}>
178
- {i18n?.t("dateRangePicker.day") ?? "Day"}
178
+ {i18n.t("dateRangePicker.day")}
179
179
  </Select.Item>
180
180
  <Select.Item value={"month" as DateRangePeriodType}>
181
- {i18n?.t("dateRangePicker.month") ?? "Month"}
181
+ {i18n.t("dateRangePicker.month")}
182
182
  </Select.Item>
183
183
  <Select.Item value={"range" as DateRangePeriodType}>
184
- {i18n?.t("dateRangePicker.range") ?? "Range"}
184
+ {i18n.t("dateRangePicker.range")}
185
185
  </Select.Item>
186
186
  </Select>
187
187
 
@@ -26,7 +26,7 @@ import {
26
26
  IconClearFormatting,
27
27
  } from "@tabler/icons-solidjs";
28
28
  import { Icon } from "../../display/Icon";
29
- import { useI18nOptional } from "../../../providers/i18n/I18nContext";
29
+ import { useI18n } from "../../../providers/i18n/I18nContext";
30
30
 
31
31
  export interface EditorToolbarProps {
32
32
  editor: Editor;
@@ -63,7 +63,7 @@ const colorIndicatorClass = clsx("absolute inset-x-1 bottom-0.5", "h-0.5 rounded
63
63
 
64
64
  export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
65
65
  const e = () => props.editor;
66
- const i18n = useI18nOptional();
66
+ const i18n = useI18n();
67
67
 
68
68
  // Track active state reactively with createEditorTransaction
69
69
  const isBold = createEditorTransaction(e, (editor) => editor.isActive("bold"));
@@ -131,7 +131,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
131
131
  <button
132
132
  type="button"
133
133
  class={btnClass(isH1)}
134
- title={i18n?.t("editorToolbar.heading1") ?? "Heading 1"}
134
+ title={i18n.t("editorToolbar.heading1")}
135
135
  onClick={() => props.editor.chain().focus().toggleHeading({ level: 1 }).run()}
136
136
  >
137
137
  <Icon icon={IconH1} size="1em" />
@@ -139,7 +139,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
139
139
  <button
140
140
  type="button"
141
141
  class={btnClass(isH2)}
142
- title={i18n?.t("editorToolbar.heading2") ?? "Heading 2"}
142
+ title={i18n.t("editorToolbar.heading2")}
143
143
  onClick={() => props.editor.chain().focus().toggleHeading({ level: 2 }).run()}
144
144
  >
145
145
  <Icon icon={IconH2} size="1em" />
@@ -152,7 +152,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
152
152
  <button
153
153
  type="button"
154
154
  class={btnClass(isBold)}
155
- title={i18n?.t("editorToolbar.bold") ?? "Bold"}
155
+ title={i18n.t("editorToolbar.bold")}
156
156
  onClick={() => props.editor.chain().focus().toggleBold().run()}
157
157
  >
158
158
  <Icon icon={IconBold} size="1em" />
@@ -160,7 +160,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
160
160
  <button
161
161
  type="button"
162
162
  class={btnClass(isItalic)}
163
- title={i18n?.t("editorToolbar.italic") ?? "Italic"}
163
+ title={i18n.t("editorToolbar.italic")}
164
164
  onClick={() => props.editor.chain().focus().toggleItalic().run()}
165
165
  >
166
166
  <Icon icon={IconItalic} size="1em" />
@@ -168,7 +168,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
168
168
  <button
169
169
  type="button"
170
170
  class={btnClass(isUnderline)}
171
- title={i18n?.t("editorToolbar.underline") ?? "Underline"}
171
+ title={i18n.t("editorToolbar.underline")}
172
172
  onClick={() => props.editor.chain().focus().toggleUnderline().run()}
173
173
  >
174
174
  <Icon icon={IconUnderline} size="1em" />
@@ -176,7 +176,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
176
176
  <button
177
177
  type="button"
178
178
  class={btnClass(isStrike)}
179
- title={i18n?.t("editorToolbar.strikethrough") ?? "Strikethrough"}
179
+ title={i18n.t("editorToolbar.strikethrough")}
180
180
  onClick={() => props.editor.chain().focus().toggleStrike().run()}
181
181
  >
182
182
  <Icon icon={IconStrikethrough} size="1em" />
@@ -186,7 +186,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
186
186
  <div class={separatorClass} />
187
187
 
188
188
  {/* 5. Text color + background color (using input[type=color]) */}
189
- <label class={colorLabelClass} title={i18n?.t("editorToolbar.textColor") ?? "Text color"}>
189
+ <label class={colorLabelClass} title={i18n.t("editorToolbar.textColor")}>
190
190
  <span class={clsx("text-sm font-bold")}>A</span>
191
191
  <div class={colorIndicatorClass} style={{ "background-color": currentColor() }} />
192
192
  <input
@@ -196,7 +196,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
196
196
  onInput={(ev) => props.editor.chain().focus().setColor(ev.currentTarget.value).run()}
197
197
  />
198
198
  </label>
199
- <label class={colorLabelClass} title={i18n?.t("editorToolbar.bgColor") ?? "Background color"}>
199
+ <label class={colorLabelClass} title={i18n.t("editorToolbar.bgColor")}>
200
200
  <span
201
201
  class={clsx("rounded px-0.5 text-sm font-bold")}
202
202
  style={{ "background-color": currentHighlight() }}
@@ -220,7 +220,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
220
220
  <button
221
221
  type="button"
222
222
  class={btnClass(isBulletList)}
223
- title={i18n?.t("editorToolbar.bulletList") ?? "Bullet list"}
223
+ title={i18n.t("editorToolbar.bulletList")}
224
224
  onClick={() => props.editor.chain().focus().toggleBulletList().run()}
225
225
  >
226
226
  <Icon icon={IconList} size="1em" />
@@ -228,7 +228,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
228
228
  <button
229
229
  type="button"
230
230
  class={btnClass(isOrderedList)}
231
- title={i18n?.t("editorToolbar.numberedList") ?? "Numbered list"}
231
+ title={i18n.t("editorToolbar.numberedList")}
232
232
  onClick={() => props.editor.chain().focus().toggleOrderedList().run()}
233
233
  >
234
234
  <Icon icon={IconListNumbers} size="1em" />
@@ -241,7 +241,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
241
241
  <button
242
242
  type="button"
243
243
  class={toolbarBtnClass}
244
- title={i18n?.t("editorToolbar.increaseIndent") ?? "Increase indent"}
244
+ title={i18n.t("editorToolbar.increaseIndent")}
245
245
  onClick={() => props.editor.chain().focus().sinkListItem("listItem").run()}
246
246
  >
247
247
  <Icon icon={IconIndentIncrease} size="1em" />
@@ -249,7 +249,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
249
249
  <button
250
250
  type="button"
251
251
  class={toolbarBtnClass}
252
- title={i18n?.t("editorToolbar.decreaseIndent") ?? "Decrease indent"}
252
+ title={i18n.t("editorToolbar.decreaseIndent")}
253
253
  onClick={() => props.editor.chain().focus().liftListItem("listItem").run()}
254
254
  >
255
255
  <Icon icon={IconIndentDecrease} size="1em" />
@@ -262,7 +262,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
262
262
  <button
263
263
  type="button"
264
264
  class={btnClass(isBlockquote)}
265
- title={i18n?.t("editorToolbar.blockquote") ?? "Blockquote"}
265
+ title={i18n.t("editorToolbar.blockquote")}
266
266
  onClick={() => props.editor.chain().focus().toggleBlockquote().run()}
267
267
  >
268
268
  <Icon icon={IconQuote} size="1em" />
@@ -270,7 +270,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
270
270
  <button
271
271
  type="button"
272
272
  class={btnClass(isCodeBlock)}
273
- title={i18n?.t("editorToolbar.codeBlock") ?? "Code block"}
273
+ title={i18n.t("editorToolbar.codeBlock")}
274
274
  onClick={() => props.editor.chain().focus().toggleCodeBlock().run()}
275
275
  >
276
276
  <Icon icon={IconCode} size="1em" />
@@ -283,7 +283,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
283
283
  <button
284
284
  type="button"
285
285
  class={btnClass(isAlignLeft)}
286
- title={i18n?.t("editorToolbar.alignLeft") ?? "Align left"}
286
+ title={i18n.t("editorToolbar.alignLeft")}
287
287
  onClick={() => props.editor.chain().focus().setTextAlign("left").run()}
288
288
  >
289
289
  <Icon icon={IconAlignLeft} size="1em" />
@@ -291,7 +291,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
291
291
  <button
292
292
  type="button"
293
293
  class={btnClass(isAlignCenter)}
294
- title={i18n?.t("editorToolbar.alignCenter") ?? "Align center"}
294
+ title={i18n.t("editorToolbar.alignCenter")}
295
295
  onClick={() => props.editor.chain().focus().setTextAlign("center").run()}
296
296
  >
297
297
  <Icon icon={IconAlignCenter} size="1em" />
@@ -299,7 +299,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
299
299
  <button
300
300
  type="button"
301
301
  class={btnClass(isAlignRight)}
302
- title={i18n?.t("editorToolbar.alignRight") ?? "Align right"}
302
+ title={i18n.t("editorToolbar.alignRight")}
303
303
  onClick={() => props.editor.chain().focus().setTextAlign("right").run()}
304
304
  >
305
305
  <Icon icon={IconAlignRight} size="1em" />
@@ -307,7 +307,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
307
307
  <button
308
308
  type="button"
309
309
  class={btnClass(isAlignJustify)}
310
- title={i18n?.t("editorToolbar.justify") ?? "Justify"}
310
+ title={i18n.t("editorToolbar.justify")}
311
311
  onClick={() => props.editor.chain().focus().setTextAlign("justify").run()}
312
312
  >
313
313
  <Icon icon={IconAlignJustified} size="1em" />
@@ -320,7 +320,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
320
320
  <button
321
321
  type="button"
322
322
  class={toolbarBtnClass}
323
- title={i18n?.t("editorToolbar.insertTable") ?? "Insert table"}
323
+ title={i18n.t("editorToolbar.insertTable")}
324
324
  onClick={() =>
325
325
  props.editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run()
326
326
  }
@@ -329,7 +329,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
329
329
  </button>
330
330
 
331
331
  {/* 16. Insert image */}
332
- <button type="button" class={toolbarBtnClass} title={i18n?.t("editorToolbar.insertImage") ?? "Insert image"} onClick={handleImageInsert}>
332
+ <button type="button" class={toolbarBtnClass} title={i18n.t("editorToolbar.insertImage")} onClick={handleImageInsert}>
333
333
  <Icon icon={IconPhoto} size="1em" />
334
334
  </button>
335
335
 
@@ -340,7 +340,7 @@ export const EditorToolbar: Component<EditorToolbarProps> = (props) => {
340
340
  <button
341
341
  type="button"
342
342
  class={toolbarBtnClass}
343
- title={i18n?.t("editorToolbar.clearFormatting") ?? "Clear formatting"}
343
+ title={i18n.t("editorToolbar.clearFormatting")}
344
344
  onClick={() => props.editor.chain().focus().clearNodes().unsetAllMarks().run()}
345
345
  >
346
346
  <Icon icon={IconClearFormatting} size="1em" />
@@ -5,6 +5,7 @@ import { DateOnly } from "@simplysm/core-common";
5
5
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
6
6
  import { fieldInputClass, type FieldSize, getFieldWrapperClass } from "./Field.styles";
7
7
  import { Invalid } from "../../form-control/Invalid";
8
+ import { useI18n } from "../../../providers/i18n/I18nContext";
8
9
 
9
10
  type DatePickerUnit = "year" | "month" | "date";
10
11
 
@@ -155,6 +156,8 @@ export const DatePicker: Component<DatePickerProps> = (props) => {
155
156
  "touchMode",
156
157
  ]);
157
158
 
159
+ const i18n = useI18n();
160
+
158
161
  // Default unit is date
159
162
  const fieldType = () => local.unit ?? "date";
160
163
 
@@ -190,12 +193,12 @@ export const DatePicker: Component<DatePickerProps> = (props) => {
190
193
  // Validation message (check in order, return first error)
191
194
  const errorMsg = createMemo(() => {
192
195
  const v = value();
193
- if (local.required && v === undefined) return "This field is required";
196
+ if (local.required && v === undefined) return i18n.t("validation.required");
194
197
  if (v !== undefined) {
195
198
  if (local.min !== undefined && v.tick < local.min.tick)
196
- return `Must be greater than or equal to ${local.min}`;
199
+ return i18n.t("validation.minDate", { min: String(local.min) });
197
200
  if (local.max !== undefined && v.tick > local.max.tick)
198
- return `Must be less than or equal to ${local.max}`;
201
+ return i18n.t("validation.maxDate", { max: String(local.max) });
199
202
  }
200
203
  return local.validate?.(v);
201
204
  });
@@ -5,6 +5,7 @@ import { DateTime } from "@simplysm/core-common";
5
5
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
6
6
  import { type FieldSize, fieldInputClass, getFieldWrapperClass } from "./Field.styles";
7
7
  import { Invalid } from "../../form-control/Invalid";
8
+ import { useI18n } from "../../../providers/i18n/I18nContext";
8
9
 
9
10
  type DateTimePickerUnit = "minute" | "second";
10
11
 
@@ -150,6 +151,8 @@ export const DateTimePicker: Component<DateTimePickerProps> = (props) => {
150
151
  "touchMode",
151
152
  ]);
152
153
 
154
+ const i18n = useI18n();
155
+
153
156
  // Default unit is minute
154
157
  const fieldType = () => local.unit ?? "minute";
155
158
 
@@ -188,12 +191,12 @@ export const DateTimePicker: Component<DateTimePickerProps> = (props) => {
188
191
  // Validation message (check in order, return first error)
189
192
  const errorMsg = createMemo(() => {
190
193
  const v = value();
191
- if (local.required && v === undefined) return "This field is required";
194
+ if (local.required && v === undefined) return i18n.t("validation.required");
192
195
  if (v !== undefined) {
193
196
  if (local.min !== undefined && v.tick < local.min.tick)
194
- return `Must be greater than or equal to ${local.min.toFormatString("yyyy-MM-dd HH:mm:ss")}`;
197
+ return i18n.t("validation.minDate", { min: local.min.toFormatString("yyyy-MM-dd HH:mm:ss") });
195
198
  if (local.max !== undefined && v.tick > local.max.tick)
196
- return `Must be less than or equal to ${local.max.toFormatString("yyyy-MM-dd HH:mm:ss")}`;
199
+ return i18n.t("validation.maxDate", { max: local.max.toFormatString("yyyy-MM-dd HH:mm:ss") });
197
200
  }
198
201
  return local.validate?.(v);
199
202
  });
@@ -20,6 +20,7 @@ import {
20
20
  } from "./Field.styles";
21
21
  import { PlaceholderFallback } from "./FieldPlaceholder";
22
22
  import { Invalid } from "../../form-control/Invalid";
23
+ import { useI18n } from "../../../providers/i18n/I18nContext";
23
24
 
24
25
  // NumberInput-specific input style (right-aligned + spinner hidden)
25
26
  const numberInputClass = clsx(
@@ -216,6 +217,8 @@ export const NumberInput: NumberInputComponent = (props) => {
216
217
  "children",
217
218
  ]);
218
219
 
220
+ const i18n = useI18n();
221
+
219
222
  // Internal string state to track editing state
220
223
  const [inputStr, setInputStr] = createSignal<string>("");
221
224
  const [isEditing, setIsEditing] = createSignal(false);
@@ -298,10 +301,10 @@ export const NumberInput: NumberInputComponent = (props) => {
298
301
  // Validation message (check in order, return first error)
299
302
  const errorMsg = createMemo(() => {
300
303
  const v = value();
301
- if (local.required && v === undefined) return "This field is required";
304
+ if (local.required && v === undefined) return i18n.t("validation.required");
302
305
  if (v !== undefined) {
303
- if (local.min !== undefined && v < local.min) return `Minimum value is ${local.min}`;
304
- if (local.max !== undefined && v > local.max) return `Maximum value is ${local.max}`;
306
+ if (local.min !== undefined && v < local.min) return i18n.t("validation.minValue", { min: String(local.min) });
307
+ if (local.max !== undefined && v > local.max) return i18n.t("validation.maxValue", { max: String(local.max) });
305
308
  }
306
309
  return local.validate?.(v);
307
310
  });
@@ -13,6 +13,7 @@ import {
13
13
  } from "./Field.styles";
14
14
  import { PlaceholderFallback } from "./FieldPlaceholder";
15
15
  import { Invalid } from "../../form-control/Invalid";
16
+ import { useI18n } from "../../../providers/i18n/I18nContext";
16
17
 
17
18
  interface TextInputSlotsContextValue {
18
19
  setPrefix: (content: SlotAccessor) => void;
@@ -178,6 +179,8 @@ const TextInputInner = (props: TextInputProps) => {
178
179
  "children",
179
180
  ]);
180
181
 
182
+ const i18n = useI18n();
183
+
181
184
  // Support controlled/uncontrolled pattern
182
185
  const [value, setValue] = createControllableSignal({
183
186
  value: () => local.value ?? "",
@@ -253,14 +256,14 @@ const TextInputInner = (props: TextInputProps) => {
253
256
  // Validation error message (check in order, return first failure message)
254
257
  const errorMsg = createMemo(() => {
255
258
  const v = value();
256
- if (local.required && !v) return "This is a required field";
259
+ if (local.required && !v) return i18n.t("validation.required");
257
260
  if (v) {
258
261
  if (local.minLength != null && v.length < local.minLength)
259
- return `Enter at least ${local.minLength} characters`;
262
+ return i18n.t("validation.minLength", { min: String(local.minLength) });
260
263
  if (local.maxLength != null && v.length > local.maxLength)
261
- return `Enter up to ${local.maxLength} characters`;
264
+ return i18n.t("validation.maxLength", { max: String(local.maxLength) });
262
265
  if (local.pattern != null && !new RegExp(local.pattern).test(v))
263
- return "The input format is invalid";
266
+ return i18n.t("validation.invalidFormat");
264
267
  }
265
268
  return local.validate?.(v);
266
269
  });
@@ -6,6 +6,7 @@ import { createIMEHandler } from "../../../hooks/createIMEHandler";
6
6
  import { type FieldSize, textAreaSizeClasses, getTextareaWrapperClass } from "./Field.styles";
7
7
  import { PlaceholderFallback } from "./FieldPlaceholder";
8
8
  import { Invalid } from "../../form-control/Invalid";
9
+ import { useI18n } from "../../../providers/i18n/I18nContext";
9
10
 
10
11
  export interface TextareaProps {
11
12
  /** Input value */
@@ -98,6 +99,8 @@ export const Textarea: Component<TextareaProps> = (props) => {
98
99
  "style",
99
100
  ]);
100
101
 
102
+ const i18n = useI18n();
103
+
101
104
  const [value, setValue] = createControllableSignal({
102
105
  value: () => local.value ?? "",
103
106
  onChange: () => local.onValueChange,
@@ -174,12 +177,12 @@ export const Textarea: Component<TextareaProps> = (props) => {
174
177
  // Validation error message (check in order, return first failure message)
175
178
  const errorMsg = createMemo(() => {
176
179
  const v = value();
177
- if (local.required && !v) return "This is a required field";
180
+ if (local.required && !v) return i18n.t("validation.required");
178
181
  if (v) {
179
182
  if (local.minLength != null && v.length < local.minLength)
180
- return `Enter at least ${local.minLength} characters`;
183
+ return i18n.t("validation.minLength", { min: String(local.minLength) });
181
184
  if (local.maxLength != null && v.length > local.maxLength)
182
- return `Enter up to ${local.maxLength} characters`;
185
+ return i18n.t("validation.maxLength", { max: String(local.maxLength) });
183
186
  }
184
187
  return local.validate?.(v);
185
188
  });
@@ -5,6 +5,7 @@ import { Time } from "@simplysm/core-common";
5
5
  import { createControllableSignal } from "../../../hooks/createControllableSignal";
6
6
  import { type FieldSize, fieldInputClass, getFieldWrapperClass } from "./Field.styles";
7
7
  import { Invalid } from "../../form-control/Invalid";
8
+ import { useI18n } from "../../../providers/i18n/I18nContext";
8
9
 
9
10
  type TimePickerUnit = "minute" | "second";
10
11
 
@@ -125,6 +126,8 @@ export const TimePicker: Component<TimePickerProps> = (props) => {
125
126
  "touchMode",
126
127
  ]);
127
128
 
129
+ const i18n = useI18n();
130
+
128
131
  // Default unit is minute
129
132
  const fieldType = () => local.unit ?? "minute";
130
133
 
@@ -163,12 +166,12 @@ export const TimePicker: Component<TimePickerProps> = (props) => {
163
166
  // Validation message (check in order, return first error)
164
167
  const errorMsg = createMemo(() => {
165
168
  const v = value();
166
- if (local.required && v === undefined) return "This field is required";
169
+ if (local.required && v === undefined) return i18n.t("validation.required");
167
170
  if (v !== undefined) {
168
171
  if (local.min !== undefined && v.tick < local.min.tick)
169
- return `Must be greater than or equal to ${local.min.toFormatString("HH:mm:ss")}`;
172
+ return i18n.t("validation.minDate", { min: local.min.toFormatString("HH:mm:ss") });
170
173
  if (local.max !== undefined && v.tick > local.max.tick)
171
- return `Must be less than or equal to ${local.max.toFormatString("HH:mm:ss")}`;
174
+ return i18n.t("validation.maxDate", { max: local.max.toFormatString("HH:mm:ss") });
172
175
  }
173
176
  return local.validate?.(v);
174
177
  });
@@ -7,6 +7,7 @@ import { NumberInput } from "../field/NumberInput";
7
7
  import { Icon } from "../../display/Icon";
8
8
  import { IconEraser, IconArrowLeft } from "@tabler/icons-solidjs";
9
9
  import type { ComponentSize } from "../../../styles/tokens.styles";
10
+ import { useI18n } from "../../../providers/i18n/I18nContext";
10
11
 
11
12
  export interface NumpadProps {
12
13
  /** Input value */
@@ -54,6 +55,7 @@ function valueToInputStr(value: number | undefined): string {
54
55
  }
55
56
 
56
57
  export const Numpad: Component<NumpadProps> = (props) => {
58
+ const i18n = useI18n();
57
59
  // Controlled/uncontrolled pattern
58
60
  const [value, setValue] = createControllableSignal({
59
61
  value: () => props.value,
@@ -151,7 +153,7 @@ export const Numpad: Component<NumpadProps> = (props) => {
151
153
  disabled={props.required && value() == null}
152
154
  onClick={handleEnter}
153
155
  >
154
- ENT
156
+ {i18n.t("numpad.enter")}
155
157
  </Button>
156
158
  </Show>
157
159
 
@@ -31,7 +31,7 @@ import { createSlotSignal } from "../../../hooks/createSlotSignal";
31
31
  import { chevronWrapperClass, getTriggerClass } from "../DropdownTrigger.styles";
32
32
  import { Invalid } from "../Invalid";
33
33
  import { TextInput } from "../field/TextInput";
34
- import { useI18nOptional } from "../../../providers/i18n/I18nContext";
34
+ import { useI18n } from "../../../providers/i18n/I18nContext";
35
35
 
36
36
  void ripple;
37
37
 
@@ -264,7 +264,7 @@ export const Select: SelectComponent = <T,>(props: SelectProps<T>) => {
264
264
  "getIsHidden",
265
265
  ]);
266
266
 
267
- const i18n = useI18nOptional();
267
+ const i18n = useI18n();
268
268
  const [open, setOpen] = createSignal(false);
269
269
 
270
270
  // Search text signal
@@ -349,7 +349,7 @@ export const Select: SelectComponent = <T,>(props: SelectProps<T>) => {
349
349
  const errorMsg = createMemo(() => {
350
350
  const v = value();
351
351
  if (local.required && (v === undefined || v === null || v === ""))
352
- return "This is a required field";
352
+ return i18n.t("validation.required");
353
353
  return local.validate?.(v);
354
354
  });
355
355
 
@@ -536,7 +536,7 @@ export const Select: SelectComponent = <T,>(props: SelectProps<T>) => {
536
536
  <TextInput
537
537
  value={searchText()}
538
538
  onValueChange={setSearchText}
539
- placeholder={i18n?.t("select.searchPlaceholder") ?? "Search..."}
539
+ placeholder={i18n.t("select.searchPlaceholder")}
540
540
  class={searchInputClass}
541
541
  />
542
542
  </Show>
@@ -549,7 +549,7 @@ export const Select: SelectComponent = <T,>(props: SelectProps<T>) => {
549
549
  class={selectAllBtnClass}
550
550
  onClick={handleSelectAll}
551
551
  >
552
- {i18n?.t("select.selectAll") ?? "Select all"}
552
+ {i18n.t("select.selectAll")}
553
553
  </button>
554
554
  <button
555
555
  type="button"
@@ -557,7 +557,7 @@ export const Select: SelectComponent = <T,>(props: SelectProps<T>) => {
557
557
  class={selectAllBtnClass}
558
558
  onClick={handleDeselectAll}
559
559
  >
560
- {i18n?.t("select.deselectAll") ?? "Deselect all"}
560
+ {i18n.t("select.deselectAll")}
561
561
  </button>
562
562
  </div>
563
563
  </Show>
@@ -566,7 +566,7 @@ export const Select: SelectComponent = <T,>(props: SelectProps<T>) => {
566
566
  {/* Unset item */}
567
567
  <Show when={showUnsetItem()}>
568
568
  <SelectItem value={undefined as T}>
569
- <span class={textMuted}>{i18n?.t("select.unset") ?? "Unset"}</span>
569
+ <span class={textMuted}>{i18n.t("select.unset")}</span>
570
570
  </SelectItem>
571
571
  </Show>
572
572
  {renderItems(visibleItems() ?? [], 0)}