lutra 0.0.33 → 0.1.4

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 (274) hide show
  1. package/README.md +4 -24
  2. package/dist/components/AspectRatio.svelte +26 -0
  3. package/dist/components/AspectRatio.svelte.d.ts +8 -0
  4. package/dist/components/Avatar.svelte +105 -0
  5. package/dist/components/Avatar.svelte.d.ts +14 -0
  6. package/dist/{display → components}/Close.svelte +25 -7
  7. package/dist/components/Close.svelte.d.ts +7 -0
  8. package/dist/components/ContextTip.svelte +41 -0
  9. package/dist/components/ContextTip.svelte.d.ts +7 -0
  10. package/dist/components/Dialog.svelte +78 -0
  11. package/dist/components/Dialog.svelte.d.ts +14 -0
  12. package/dist/components/Icon.svelte +62 -0
  13. package/dist/components/Icon.svelte.d.ts +8 -0
  14. package/dist/{display → components}/IconButton.svelte +43 -14
  15. package/dist/components/IconButton.svelte.d.ts +16 -0
  16. package/dist/components/Image.svelte +172 -0
  17. package/dist/components/Image.svelte.d.ts +56 -0
  18. package/dist/{display → components}/Indicator.svelte +44 -9
  19. package/dist/components/Indicator.svelte.d.ts +12 -0
  20. package/dist/{display → components}/Inset.svelte +8 -3
  21. package/dist/components/Inset.svelte.d.ts +7 -0
  22. package/dist/components/Layout.svelte +33 -0
  23. package/dist/components/Layout.svelte.d.ts +11 -0
  24. package/dist/components/MenuDropdown.svelte +195 -0
  25. package/dist/components/MenuDropdown.svelte.d.ts +16 -0
  26. package/dist/{nav → components}/MenuItem.svelte +46 -38
  27. package/dist/components/MenuItem.svelte.d.ts +11 -0
  28. package/dist/components/MenuItemContent.svelte +25 -0
  29. package/dist/components/MenuItemContent.svelte.d.ts +10 -0
  30. package/dist/{nav → components}/MenuTypes.d.ts +19 -5
  31. package/dist/components/Modal.svelte +149 -0
  32. package/dist/components/Modal.svelte.d.ts +16 -0
  33. package/dist/{display → components}/Notification.svelte +33 -22
  34. package/dist/components/Notification.svelte.d.ts +12 -0
  35. package/dist/components/Overlay.svelte +31 -0
  36. package/dist/components/Overlay.svelte.d.ts +14 -0
  37. package/dist/{layout → components}/OverlayContainer.svelte +6 -3
  38. package/dist/{layout → components}/OverlayContainer.svelte.d.ts +4 -1
  39. package/dist/components/OverlayLayer.svelte +168 -0
  40. package/dist/components/OverlayLayer.svelte.d.ts +8 -0
  41. package/dist/components/PageContent.svelte +108 -0
  42. package/dist/components/PageContent.svelte.d.ts +38 -0
  43. package/dist/components/TabbedContent.svelte +74 -0
  44. package/dist/components/TabbedContent.svelte.d.ts +11 -0
  45. package/dist/components/TabbedContentItem.svelte +33 -0
  46. package/dist/components/TabbedContentItem.svelte.d.ts +10 -0
  47. package/dist/components/Table.svelte +41 -0
  48. package/dist/components/Table.svelte.d.ts +13 -0
  49. package/dist/{nav → components}/Tabs.svelte +99 -41
  50. package/dist/components/Tabs.svelte.d.ts +20 -0
  51. package/dist/components/Tag.svelte +120 -0
  52. package/dist/components/Tag.svelte.d.ts +21 -0
  53. package/dist/components/Theme.svelte +105 -0
  54. package/dist/components/Theme.svelte.d.ts +17 -0
  55. package/dist/{display → components}/Tooltip.svelte +41 -16
  56. package/dist/components/Tooltip.svelte.d.ts +12 -0
  57. package/dist/components/UIContent.svelte +19 -0
  58. package/dist/components/UIContent.svelte.d.ts +7 -0
  59. package/dist/components/index.d.ts +28 -0
  60. package/dist/components/index.js +29 -0
  61. package/dist/{display → components}/notifications.svelte.d.ts +1 -1
  62. package/dist/{display → components}/notifications.svelte.js +3 -4
  63. package/dist/{layout → components}/overlays.svelte.d.ts +4 -2
  64. package/dist/config.d.ts +30 -0
  65. package/dist/config.js +18 -0
  66. package/dist/css/1-props.css +440 -0
  67. package/dist/css/2-base.css +343 -0
  68. package/dist/css/3-typo.css +106 -0
  69. package/dist/css/4-layout.css +368 -0
  70. package/dist/css/5-media.css +116 -0
  71. package/dist/css/lutra.css +7 -0
  72. package/dist/css/themes/DefaultTheme.css +209 -0
  73. package/dist/form/Button.svelte +35 -16
  74. package/dist/form/Button.svelte.d.ts +8 -19
  75. package/dist/form/Datepicker.svelte +311 -0
  76. package/dist/form/Datepicker.svelte.d.ts +9 -0
  77. package/dist/form/FieldContent.svelte +69 -44
  78. package/dist/form/FieldContent.svelte.d.ts +7 -17
  79. package/dist/form/FieldError.svelte +16 -6
  80. package/dist/form/FieldError.svelte.d.ts +4 -15
  81. package/dist/form/Fieldset.svelte +48 -13
  82. package/dist/form/Fieldset.svelte.d.ts +5 -16
  83. package/dist/form/Form.svelte +158 -74
  84. package/dist/form/Form.svelte.d.ts +17 -17
  85. package/dist/form/{FieldActions.svelte → FormActions.svelte} +29 -17
  86. package/dist/form/FormActions.svelte.d.ts +9 -0
  87. package/dist/form/FormSection.svelte +96 -0
  88. package/dist/form/FormSection.svelte.d.ts +9 -0
  89. package/dist/form/ImageUpload.svelte +134 -94
  90. package/dist/form/ImageUpload.svelte.d.ts +5 -16
  91. package/dist/form/Input.svelte +254 -136
  92. package/dist/form/Input.svelte.d.ts +12 -21
  93. package/dist/form/InputLength.svelte +15 -5
  94. package/dist/form/InputLength.svelte.d.ts +4 -15
  95. package/dist/form/Label.svelte +55 -11
  96. package/dist/form/Label.svelte.d.ts +6 -15
  97. package/dist/form/LogoUpload.svelte +36 -21
  98. package/dist/form/LogoUpload.svelte.d.ts +4 -15
  99. package/dist/form/Select.svelte +100 -50
  100. package/dist/form/Select.svelte.d.ts +5 -16
  101. package/dist/form/Textarea.svelte +200 -98
  102. package/dist/form/Textarea.svelte.d.ts +11 -24
  103. package/dist/form/Toggle.svelte +3 -1
  104. package/dist/form/Toggle.svelte.d.ts +4 -1
  105. package/dist/form/client.svelte.d.ts +1 -0
  106. package/dist/form/client.svelte.js +6 -2
  107. package/dist/form/form.d.ts +10 -9
  108. package/dist/form/form.js +37 -32
  109. package/dist/form/index.d.ts +3 -4
  110. package/dist/form/index.js +3 -4
  111. package/dist/form/types.d.ts +9 -16
  112. package/dist/icons/IconAlert.svelte.d.ts +4 -1
  113. package/dist/icons/IconCopy.svelte.d.ts +4 -1
  114. package/dist/icons/IconDone.svelte.d.ts +4 -1
  115. package/dist/icons/IconError.svelte.d.ts +4 -1
  116. package/dist/icons/IconHelp.svelte.d.ts +4 -1
  117. package/dist/icons/IconHide.svelte.d.ts +4 -1
  118. package/dist/icons/IconInfo.svelte.d.ts +4 -1
  119. package/dist/icons/IconLink.svelte.d.ts +4 -1
  120. package/dist/icons/IconMenuBurger.svelte.d.ts +4 -1
  121. package/dist/icons/IconMenuDots.svelte.d.ts +4 -1
  122. package/dist/icons/IconSearch.svelte.d.ts +4 -1
  123. package/dist/icons/IconShow.svelte.d.ts +4 -1
  124. package/dist/icons/IconSuccess.svelte.d.ts +4 -1
  125. package/dist/icons/IconWarning.svelte.d.ts +4 -1
  126. package/dist/index.d.ts +3 -1
  127. package/dist/index.js +3 -2
  128. package/dist/types.d.ts +39 -0
  129. package/dist/types.js +25 -0
  130. package/dist/util/StringOrComponent.svelte +20 -0
  131. package/dist/util/StringOrComponent.svelte.d.ts +8 -0
  132. package/dist/util/StringOrSnippet.svelte +16 -0
  133. package/dist/util/StringOrSnippet.svelte.d.ts +8 -0
  134. package/dist/{utils → util}/dom.js +1 -2
  135. package/dist/util/locale.d.ts +1 -0
  136. package/dist/util/locale.js +47 -0
  137. package/dist/util/settings.d.ts +4 -0
  138. package/package.json +35 -79
  139. package/dist/color.css +0 -0
  140. package/dist/display/Avatar.svelte +0 -61
  141. package/dist/display/Avatar.svelte.d.ts +0 -19
  142. package/dist/display/Badge.svelte +0 -91
  143. package/dist/display/Badge.svelte.d.ts +0 -30
  144. package/dist/display/Callout.svelte +0 -109
  145. package/dist/display/Callout.svelte.d.ts +0 -28
  146. package/dist/display/Close.svelte.d.ts +0 -18
  147. package/dist/display/Code.svelte +0 -190
  148. package/dist/display/Code.svelte.d.ts +0 -32
  149. package/dist/display/ContextTip.svelte +0 -23
  150. package/dist/display/ContextTip.svelte.d.ts +0 -18
  151. package/dist/display/DataList.svelte +0 -16
  152. package/dist/display/DataList.svelte.d.ts +0 -21
  153. package/dist/display/Details.svelte +0 -49
  154. package/dist/display/Details.svelte.d.ts +0 -27
  155. package/dist/display/Hero.svelte +0 -50
  156. package/dist/display/Hero.svelte.d.ts +0 -26
  157. package/dist/display/Icon.svelte +0 -39
  158. package/dist/display/Icon.svelte.d.ts +0 -19
  159. package/dist/display/IconButton.svelte.d.ts +0 -27
  160. package/dist/display/Image.svelte +0 -91
  161. package/dist/display/Image.svelte.d.ts +0 -26
  162. package/dist/display/Indicator.svelte.d.ts +0 -23
  163. package/dist/display/Inset.svelte.d.ts +0 -18
  164. package/dist/display/LineChart.svelte +0 -385
  165. package/dist/display/LineChart.svelte.d.ts +0 -24
  166. package/dist/display/LoadingIndicator.svelte +0 -33
  167. package/dist/display/LoadingIndicator.svelte.d.ts +0 -15
  168. package/dist/display/Modal.svelte +0 -116
  169. package/dist/display/Modal.svelte.d.ts +0 -27
  170. package/dist/display/Notification.svelte.d.ts +0 -23
  171. package/dist/display/Panel.svelte +0 -23
  172. package/dist/display/Panel.svelte.d.ts +0 -19
  173. package/dist/display/Popup.svelte +0 -111
  174. package/dist/display/Popup.svelte.d.ts +0 -25
  175. package/dist/display/Stat.svelte +0 -81
  176. package/dist/display/Stat.svelte.d.ts +0 -30
  177. package/dist/display/Table.svelte +0 -28
  178. package/dist/display/Table.svelte.d.ts +0 -24
  179. package/dist/display/TablePaginator.svelte +0 -51
  180. package/dist/display/TablePaginator.svelte.d.ts +0 -21
  181. package/dist/display/Tag.svelte +0 -90
  182. package/dist/display/Tag.svelte.d.ts +0 -32
  183. package/dist/display/Tooltip.svelte.d.ts +0 -23
  184. package/dist/display/chart.d.ts +0 -78
  185. package/dist/display/chart.js +0 -212
  186. package/dist/display/index.d.ts +0 -24
  187. package/dist/display/index.js +0 -24
  188. package/dist/form/FieldActions.svelte.d.ts +0 -20
  189. package/dist/form/FieldContainer.svelte +0 -37
  190. package/dist/form/FieldContainer.svelte.d.ts +0 -19
  191. package/dist/form/FieldSection.svelte +0 -86
  192. package/dist/form/FieldSection.svelte.d.ts +0 -20
  193. package/dist/layout/Layout.svelte +0 -47
  194. package/dist/layout/Layout.svelte.d.ts +0 -22
  195. package/dist/layout/LayoutFooter.svelte +0 -21
  196. package/dist/layout/LayoutFooter.svelte.d.ts +0 -18
  197. package/dist/layout/LayoutGrid.svelte +0 -51
  198. package/dist/layout/LayoutGrid.svelte.d.ts +0 -27
  199. package/dist/layout/LayoutHeader.svelte +0 -97
  200. package/dist/layout/LayoutHeader.svelte.d.ts +0 -34
  201. package/dist/layout/LayoutSideMenu.svelte +0 -55
  202. package/dist/layout/LayoutSideMenu.svelte.d.ts +0 -21
  203. package/dist/layout/LayoutTypes.d.ts +0 -15
  204. package/dist/layout/LayoutTypes.js +0 -9
  205. package/dist/layout/Overlay.svelte +0 -20
  206. package/dist/layout/Overlay.svelte.d.ts +0 -25
  207. package/dist/layout/OverlayLayer.svelte +0 -140
  208. package/dist/layout/OverlayLayer.svelte.d.ts +0 -19
  209. package/dist/layout/PageContent.svelte +0 -82
  210. package/dist/layout/PageContent.svelte.d.ts +0 -25
  211. package/dist/layout/Theme.svelte +0 -243
  212. package/dist/layout/Theme.svelte.d.ts +0 -19
  213. package/dist/layout/UIContent.svelte +0 -15
  214. package/dist/layout/UIContent.svelte.d.ts +0 -18
  215. package/dist/layout/index.d.ts +0 -11
  216. package/dist/layout/index.js +0 -11
  217. package/dist/nav/Breadcrumb.svelte +0 -82
  218. package/dist/nav/Breadcrumb.svelte.d.ts +0 -28
  219. package/dist/nav/Menu.svelte +0 -170
  220. package/dist/nav/Menu.svelte.d.ts +0 -27
  221. package/dist/nav/MenuItem.svelte.d.ts +0 -22
  222. package/dist/nav/NavMenu.svelte +0 -181
  223. package/dist/nav/NavMenu.svelte.d.ts +0 -19
  224. package/dist/nav/TabbedContent.svelte +0 -43
  225. package/dist/nav/TabbedContent.svelte.d.ts +0 -23
  226. package/dist/nav/Tabs.svelte.d.ts +0 -25
  227. package/dist/nav/index.d.ts +0 -7
  228. package/dist/nav/index.js +0 -6
  229. package/dist/style.css +0 -950
  230. package/dist/typo/Clamp.svelte +0 -25
  231. package/dist/typo/Clamp.svelte.d.ts +0 -24
  232. package/dist/typo/H.svelte +0 -52
  233. package/dist/typo/H.svelte.d.ts +0 -28
  234. package/dist/typo/H1.svelte +0 -14
  235. package/dist/typo/H1.svelte.d.ts +0 -26
  236. package/dist/typo/H2.svelte +0 -14
  237. package/dist/typo/H2.svelte.d.ts +0 -26
  238. package/dist/typo/H3.svelte +0 -14
  239. package/dist/typo/H3.svelte.d.ts +0 -26
  240. package/dist/typo/H4.svelte +0 -14
  241. package/dist/typo/H4.svelte.d.ts +0 -26
  242. package/dist/typo/H5.svelte +0 -14
  243. package/dist/typo/H5.svelte.d.ts +0 -26
  244. package/dist/typo/H6.svelte +0 -14
  245. package/dist/typo/H6.svelte.d.ts +0 -26
  246. package/dist/typo/P.svelte +0 -34
  247. package/dist/typo/P.svelte.d.ts +0 -26
  248. package/dist/typo/index.d.ts +0 -9
  249. package/dist/typo/index.js +0 -9
  250. package/dist/utils/StringOrComponent.svelte +0 -14
  251. package/dist/utils/StringOrComponent.svelte.d.ts +0 -19
  252. package/dist/utils/StringOrSnippet.svelte +0 -11
  253. package/dist/utils/StringOrSnippet.svelte.d.ts +0 -19
  254. package/dist/utils/defaults.d.ts +0 -4
  255. package/dist/utils/hooks.server.d.ts +0 -2
  256. package/dist/utils/hooks.server.js +0 -16
  257. package/dist/utils/id.d.ts +0 -1
  258. package/dist/utils/id.js +0 -3
  259. package/dist/utils/index.d.ts +0 -9
  260. package/dist/utils/index.js +0 -6
  261. package/dist/utils/isSnippet.d.ts +0 -3
  262. package/dist/utils/isSnippet.js +0 -11
  263. /package/dist/{nav → components}/MenuTypes.js +0 -0
  264. /package/dist/{layout → components}/overlays.svelte.js +0 -0
  265. /package/dist/{utils → util}/attr.d.ts +0 -0
  266. /package/dist/{utils → util}/attr.js +0 -0
  267. /package/dist/{utils → util}/color.d.ts +0 -0
  268. /package/dist/{utils → util}/color.js +0 -0
  269. /package/dist/{utils → util}/dom.d.ts +0 -0
  270. /package/dist/{utils → util}/keyboard.svelte.d.ts +0 -0
  271. /package/dist/{utils → util}/keyboard.svelte.js +0 -0
  272. /package/dist/{utils/defaults.js → util/settings.js} +0 -0
  273. /package/dist/{utils → util}/transitions.d.ts +0 -0
  274. /package/dist/{utils → util}/transitions.js +0 -0
@@ -1,28 +1,44 @@
1
- <script lang="ts">import Icon from "../display/Icon.svelte";
2
- import { getContext } from "svelte";
3
- let {
4
- href,
5
- type = "button",
6
- class: className,
7
- size = "md",
8
- kind = "default",
9
- disabled = false,
10
- icon,
11
- onclick,
12
- children
13
- } = $props();
14
- const form = getContext("form");
1
+ <script lang="ts">
2
+ import Icon from '../components/Icon.svelte';
3
+ import { getContext, type Component, type Snippet } from 'svelte';
4
+ import type { LutraForm } from './types.js';
5
+
6
+ let {
7
+ href,
8
+ type = 'button',
9
+ class: className,
10
+ size = 'md',
11
+ kind = 'default',
12
+ disabled = false,
13
+ icon,
14
+ onclick,
15
+ children,
16
+ }: {
17
+ href?: string;
18
+ type?: 'button' | 'submit' | 'reset';
19
+ kind?: 'default' | 'outlined' | 'secondary' | 'warn';
20
+ size?: 'sm' | 'md' | 'lg' | 'xl';
21
+ class?: string;
22
+ disabled?: boolean;
23
+ icon?: string | Component;
24
+ onclick?: (event: MouseEvent) => void;
25
+ children: Snippet;
26
+ } = $props();
27
+
28
+ const form = getContext<LutraForm<any>>('form');
29
+ const align = getContext('form.actions.align');
30
+
15
31
  </script>
16
32
 
17
33
  {#if href}
18
- <a class="Button Link button {size} {kind} {className}" {href} {onclick}>
34
+ <a class="Button Link button {size} {kind} {className} {align}" {href} {onclick}>
19
35
  {#if icon}
20
36
  <Icon {icon} />
21
37
  {/if}
22
38
  {@render children()}
23
39
  </a>
24
40
  {:else}
25
- <button class="Button button {size} {kind} {className}" type={type} disabled={disabled || form?.state === 'loading'} {onclick}>
41
+ <button class="Button button {size} {kind} {className} {align}" type={type} disabled={disabled || form?.state === 'loading'} {onclick}>
26
42
  {#if icon}
27
43
  <Icon {icon} />
28
44
  {/if}
@@ -36,4 +52,7 @@ const form = getContext("form");
36
52
  align-items: center;
37
53
  justify-content: center;
38
54
  }
55
+ .Button.full {
56
+ width: 100%;
57
+ }
39
58
  </style>
@@ -1,26 +1,15 @@
1
1
  import { type Component, type Snippet } from 'svelte';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports;
10
- z_$$bindings?: Bindings;
11
- }
12
- declare const Button: $$__sveltets_2_IsomorphicComponent<{
2
+ type $$ComponentProps = {
13
3
  href?: string;
14
- type?: "button" | "submit" | "reset";
15
- kind?: "default" | "outlined" | "secondary" | "warn";
16
- size?: "sm" | "md" | "lg" | "xl";
4
+ type?: 'button' | 'submit' | 'reset';
5
+ kind?: 'default' | 'outlined' | 'secondary' | 'warn';
6
+ size?: 'sm' | 'md' | 'lg' | 'xl';
17
7
  class?: string;
18
8
  disabled?: boolean;
19
- icon?: string | Snippet | Component;
9
+ icon?: string | Component;
20
10
  onclick?: (event: MouseEvent) => void;
21
11
  children: Snippet;
22
- }, {
23
- [evt: string]: CustomEvent<any>;
24
- }, {}, {}, "">;
25
- type Button = InstanceType<typeof Button>;
12
+ };
13
+ declare const Button: Component<$$ComponentProps, {}, "">;
14
+ type Button = ReturnType<typeof Button>;
26
15
  export default Button;
@@ -0,0 +1,311 @@
1
+ <script lang="ts">
2
+ import TabbedContent from "../components/TabbedContent.svelte";
3
+ import TabbedContentItem from "../components/TabbedContentItem.svelte";
4
+ import UiContent from "../components/UIContent.svelte";
5
+ import { getLocaleFirstDayOfWeek } from "../util/locale.js";
6
+
7
+ let {
8
+ range
9
+ }: {
10
+ range?: {
11
+ min?: Date;
12
+ max?: Date;
13
+ }
14
+ } = $props();
15
+
16
+ const currentYear = new Date().getFullYear();
17
+ const startYear = Math.max(2020, currentYear - 5);
18
+ let years = $state(
19
+ Array.from(
20
+ { length: currentYear - startYear + 1 },
21
+ (_, i) => startYear + i
22
+ ).reverse()
23
+ );
24
+
25
+ let selectedStartYear = $state(currentYear);
26
+ let selectedEndYear = $state(currentYear);
27
+ let selectedStartMonth = $state(1);
28
+ let selectedEndMonth = $state(12);
29
+ let selectedStartDay = $state(1);
30
+ let selectedEndDay = $state(31);
31
+
32
+ let months = $state(
33
+ Array.from(
34
+ { length: 12 },
35
+ (_, i) => i + 1
36
+ )
37
+ );
38
+
39
+ const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
40
+ const dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
41
+ let monthName = $derived(monthNames[selectedStartMonth - 1]);
42
+
43
+ let localeFirstDay = $state(getLocaleFirstDayOfWeek());
44
+ let dayNamesOrdered = $derived([
45
+ ...dayNames.slice(localeFirstDay),
46
+ ...dayNames.slice(0, localeFirstDay)
47
+ ]);
48
+
49
+ function daysInMonth(year: number, month: number): number {
50
+ return new Date(year, month, 0).getDate();
51
+ }
52
+
53
+ let daysInCurrentMonth = $derived(daysInMonth(selectedStartYear, selectedStartMonth));
54
+ let firstWeekdayIndex = $derived(new Date(selectedStartYear, selectedStartMonth - 1, 1).getDay());
55
+ let firstWeekdayOffset = $derived((7 + firstWeekdayIndex - localeFirstDay) % 7);
56
+ let daysGrid = $derived((() => {
57
+ const totalCells = 42; // 6 rows x 7 days
58
+ const grid: Array<number | null> = [];
59
+ for (let i = 0; i < totalCells; i++) {
60
+ const dayNumber = i - firstWeekdayOffset + 1;
61
+ grid.push(dayNumber >= 1 && dayNumber <= daysInCurrentMonth ? dayNumber : null);
62
+ }
63
+ return grid;
64
+ })());
65
+
66
+ $effect(() => {
67
+ if (selectedStartDay > daysInCurrentMonth) {
68
+ selectedStartDay = daysInCurrentMonth;
69
+ }
70
+ if (selectedStartDay < 1) {
71
+ selectedStartDay = 1;
72
+ }
73
+ });
74
+
75
+ function pad2(n: number): string { return n < 10 ? `0${n}` : `${n}`; }
76
+ function toLocalDateTimeInputValue(date: Date): string {
77
+ const y = date.getFullYear();
78
+ const m = pad2(date.getMonth() + 1);
79
+ const d = pad2(date.getDate());
80
+ const hh = pad2(date.getHours());
81
+ const mm = pad2(date.getMinutes());
82
+ return `${y}-${m}-${d}T${hh}:${mm}`;
83
+ }
84
+
85
+ let startValue = $derived.by(() => {
86
+ return toLocalDateTimeInputValue(new Date(selectedStartYear, selectedStartMonth - 1, selectedStartDay));
87
+ });
88
+ let endValue = $derived.by(() => {
89
+ return toLocalDateTimeInputValue(new Date(selectedEndYear, selectedEndMonth - 1, selectedEndDay));
90
+ });
91
+
92
+ </script>
93
+
94
+ <UiContent>
95
+ <div class="Datepicker">
96
+ <div class="Fields">
97
+ <div class="Field Start">
98
+ <h6>From</h6>
99
+ <input type="datetime-local" bind:value={startValue} />
100
+ </div>
101
+ <div class="Field End">
102
+ <h6>To</h6>
103
+ <input type="datetime-local" bind:value={endValue} />
104
+ </div>
105
+ </div>
106
+ <div class="Components">
107
+ <div class="ComponentContainer YearComponent">
108
+ <div class="Component Years">
109
+ {#each years as year}
110
+ <button type="button" class="Year" class:selected={selectedStartYear === year} onclick={() => selectedStartYear = year}>{year}</button>
111
+ {/each}
112
+ </div>
113
+ </div>
114
+ <div class="ComponentContainer MonthComponent">
115
+ <div class="Component Months">
116
+ {#each months as month}
117
+ <button type="button" class="Month" class:selected={selectedStartMonth === month} onclick={() => selectedStartMonth = month}>
118
+ <span class="MonthName">{monthNames[month - 1]}</span>
119
+ <span class="MonthNumber">{month}</span>
120
+ </button>
121
+ {/each}
122
+ </div>
123
+ </div>
124
+ <div class="ComponentContainer DayComponent">
125
+ <div class="Component Days">
126
+ {#each dayNamesOrdered as name}
127
+ <div class="DayName">{name}</div>
128
+ {/each}
129
+ {#each daysGrid as cell}
130
+ {#if cell === null}
131
+ <div class="Day Empty"></div>
132
+ {:else}
133
+ <button type="button" class="Day" class:selected={selectedStartDay === cell} onmousedown={(e) => {
134
+ e.preventDefault();
135
+ selectedStartDay = cell;
136
+ }}>{cell}</button>
137
+ {/if}
138
+ {/each}
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </UiContent>
144
+
145
+ <style>
146
+ button {
147
+ background-color: transparent;
148
+ border: none;
149
+ padding: 0;
150
+ cursor: pointer;
151
+ transition: all var(--transition-duration-fast) var(--transition-timing-function);
152
+ margin: 0;
153
+ }
154
+ .Datepicker {
155
+ width: fit-content;
156
+ display: grid;
157
+ grid-template-rows: 1fr auto;
158
+ border: var(--border-size-thin) solid var(--border-color);
159
+ border-radius: var(--border-radius-sm);
160
+ }
161
+ .Components, .Fields {
162
+ display: grid;
163
+ grid-template-columns: subgrid;
164
+ grid-column: span 3;
165
+ padding: var(--space-md);
166
+ }
167
+ .Components {
168
+ flex-direction: row;
169
+ justify-content: start;
170
+ align-items: start;
171
+ gap: var(--space-md);
172
+ user-select: none;
173
+ }
174
+ .YearComponent,
175
+ .MonthComponent {
176
+ grid-column: span 1;
177
+ }
178
+ .DayComponent {
179
+ grid-column: span 1;
180
+ }
181
+ .Years {
182
+ display: flex;
183
+ flex-direction: column;
184
+ justify-content: start;
185
+ align-items: start;
186
+ gap: var(--space-md);
187
+ }
188
+ .Year {
189
+ display: block;
190
+ font-size: 2em;
191
+ padding: var(--space-sm);
192
+ text-box: trim-both cap alphabetic;
193
+ }
194
+ .Months {
195
+ display: grid;
196
+ grid-template-columns: auto 1fr;
197
+ gap: var(--space-sm);
198
+ }
199
+ .Month {
200
+ display: grid;
201
+ grid-template-columns: subgrid;
202
+ grid-column: span 2;
203
+ line-height: 1;
204
+ padding: var(--space-sm);
205
+ text-align: right;
206
+ white-space: nowrap;
207
+ }
208
+ .MonthNumber {
209
+ font-size: 1.5em;
210
+ text-align: right;
211
+ text-box: trim-both cap alphabetic;
212
+ }
213
+
214
+ .MonthName {
215
+ font-size: 0.75em;
216
+ text-align: left;
217
+ text-box: trim-both cap alphabetic;
218
+ opacity: 0.5;
219
+ }
220
+
221
+ .Days {
222
+ display: grid;
223
+ grid-template-columns: repeat(7, 1fr);
224
+ flex-direction: row;
225
+ flex-wrap: wrap;
226
+ justify-content: start;
227
+ align-items: start;
228
+ gap: var(--space-sm);
229
+ }
230
+ .DayName {
231
+ display: flex;
232
+ text-box: trim-both cap alphabetic;
233
+ justify-content: center;
234
+ font-size: 0.75em;
235
+ opacity: 0.5;
236
+ align-items: center;
237
+ }
238
+ .Day {
239
+ display: flex;
240
+ text-box: trim-both cap alphabetic;
241
+ justify-content: center;
242
+ align-items: center;
243
+ border: var(--border-size-thin) solid var(--border-color);
244
+ border-radius: calc(var(--border-radius-sm) / 2);
245
+ padding: var(--space-050);
246
+ line-height: 1;
247
+ text-box: trim-both cap alphabetic;
248
+ }
249
+ .Day.Empty {
250
+ border-color: transparent;
251
+ }
252
+ .selected {
253
+ background-color: var(--background-selected);
254
+ border-radius: calc(var(--border-radius-sm) / 2);
255
+ }
256
+
257
+ .Fields {
258
+ display: grid;
259
+ grid-template-columns: 1fr 1fr;
260
+ border-bottom: var(--border-size-thin) solid var(--border-color);
261
+ padding: 0;
262
+ }
263
+ .Field {
264
+ display: grid;
265
+ grid-areas: "content";
266
+ border-right: var(--field-border-size) var(--field-border-style) var(--field-border-color);
267
+ align-items: center;
268
+ }
269
+ .Field:first-child { border-top-left-radius: var(--border-radius-sm); }
270
+ .Field:last-child { border-top-right-radius: var(--border-radius-sm); border-right: none; }
271
+ .Field h6 {
272
+ font-size: 0.85em;
273
+ font-weight: 400;
274
+ opacity: 0.5;
275
+ padding: var(--space-sm);
276
+ margin: 0;
277
+ height: 100%;
278
+ line-height: 1.5;
279
+ text-box: trim-both cap alphabetic;
280
+ }
281
+ .Field input {
282
+ font-family: var(--font-family-mono);
283
+ font-weight: 500;
284
+ font-size: 1.5em;
285
+ border: none;
286
+ padding: var(--space-md) var(--space-sm);
287
+ line-height: 1.5;
288
+ width: 100%;
289
+ text-box: trim-both cap alphabetic;
290
+ outline: none;
291
+ }
292
+ .Field input:focus-visible {
293
+ outline: none;
294
+ }
295
+ .Field:has(input:focus-visible) {
296
+ outline: var(--focus-ring);
297
+ border-color: var(--focus-ring-color);
298
+ }
299
+ /* Hide native datetime-local picker UI; we render our own date grid */
300
+ .Field input[type="datetime-local"] {
301
+ -webkit-appearance: textfield;
302
+ appearance: textfield;
303
+ }
304
+ .Field input[type="datetime-local"]::-webkit-calendar-picker-indicator {
305
+ display: none;
306
+ }
307
+ .Field input[type="datetime-local"]::-webkit-clear-button,
308
+ .Field input[type="datetime-local"]::-webkit-inner-spin-button {
309
+ display: none;
310
+ }
311
+ </style>
@@ -0,0 +1,9 @@
1
+ type $$ComponentProps = {
2
+ range?: {
3
+ min?: Date;
4
+ max?: Date;
5
+ };
6
+ };
7
+ declare const Datepicker: import("svelte").Component<$$ComponentProps, {}, "">;
8
+ type Datepicker = ReturnType<typeof Datepicker>;
9
+ export default Datepicker;
@@ -1,22 +1,47 @@
1
- <script lang="ts">import Label from "./Label.svelte";
2
- import FieldError from "./FieldError.svelte";
3
- import StringOrSnippet from "../utils/StringOrSnippet.svelte";
4
- let {
5
- id,
6
- contained,
7
- prefix,
8
- suffix,
9
- label,
10
- labelTip,
11
- help,
12
- type = "text",
13
- direction = "column",
14
- // 'row' | 'column'
15
- required,
16
- children,
17
- field,
18
- issue
19
- } = $props();
1
+ <script lang="ts">
2
+ import { getContext, type Snippet } from "svelte";
3
+ import Label from "./Label.svelte";
4
+ import FieldError from "./FieldError.svelte";
5
+ import type { FormField, FormIssue } from "./types.js";
6
+ import StringOrSnippet from "../util/StringOrSnippet.svelte";
7
+
8
+ /**
9
+ * @description
10
+ * This component is used internally by the Input, Select, etc. components to render the label and the input field in a consistent way.
11
+ */
12
+ let {
13
+ id,
14
+ contained,
15
+ prefix,
16
+ suffix,
17
+ label,
18
+ labelTip,
19
+ labelHelp,
20
+ help,
21
+ type = "text",
22
+ direction = 'column', // 'row' | 'column'
23
+ required,
24
+ children,
25
+ field,
26
+ issue,
27
+ }: {
28
+ id: string;
29
+ contained?: boolean;
30
+ prefix?: string | Snippet;
31
+ suffix?: string | Snippet;
32
+ help?: string | Snippet;
33
+ type?: string;
34
+ label?: string | Snippet;
35
+ labelTip?: string | Snippet;
36
+ labelHelp?: string | Snippet;
37
+ direction?: 'row' | 'column';
38
+ required?: boolean;
39
+ children: Snippet;
40
+ field?: FormField;
41
+ issue?: FormIssue;
42
+ } = $props();
43
+
44
+ if(contained === undefined) { contained = getContext('lutra.form.contained') ?? getContext('lutra.contained') ?? false; }
20
45
  </script>
21
46
 
22
47
  {#snippet _prefix()}
@@ -33,7 +58,7 @@ let {
33
58
 
34
59
  <div class="FieldContentContainer">
35
60
  <div class="FieldContent {type} {direction}" class:contained>
36
- <Label {label} tip={labelTip} {id} {required} />
61
+ <Label {label} tip={labelTip} help={labelHelp} {id} {required} />
37
62
  {#if contained}
38
63
  <div
39
64
  class="Field"
@@ -80,13 +105,13 @@ let {
80
105
  .FieldContentContainer {
81
106
  display: flex;
82
107
  flex-direction: column;
83
- gap: 0.75em;
108
+ gap: var(--form-field-gap, var(--space-sm));
84
109
  }
85
110
  .FieldContent {
86
111
  display: flex;
87
- gap: 0.75em;
112
+ gap: var(--form-label-gap, var(--space-sm));
88
113
  flex-direction: column;
89
- font-size: var(--font-size, 1em);
114
+ font-size: 1em;
90
115
  }
91
116
  .FieldContent.row {
92
117
  flex-direction: row-reverse;
@@ -95,14 +120,13 @@ let {
95
120
  flex-shrink: 0;
96
121
  }
97
122
  .Field {
98
- background-color: var(--field-bg);
123
+ background: var(--field-background, transparent);
99
124
  border: var(--field-border-size) var(--field-border-style) var(--field-border-color);
100
- border-radius: var(--field-radius);
125
+ border-radius: var(--field-border-radius);
101
126
  display: flex;
102
127
  }
103
- .Field:has(input:user-invalid),
104
128
  .Field.invalid {
105
- border-color: var(--field-border-color-error);
129
+ border-color: var(--field-border-color-invalid);
106
130
  }
107
131
  .Field > *:not(input) {
108
132
  flex-grow: 0;
@@ -111,9 +135,9 @@ let {
111
135
  .Fix {
112
136
  display: flex;
113
137
  align-items: center;
114
- padding-inline: 0.75em;
138
+ padding-inline: var(--form-field-gap, var(--space-md));
115
139
  font-size: 1em;
116
- line-height: 1.5;
140
+ text-box: trim-both cap alphabetic;
117
141
  color: var(--text-subtle);
118
142
  }
119
143
  .Suffix {
@@ -122,22 +146,23 @@ let {
122
146
  .Prefix {
123
147
  padding-inline-end: 0;
124
148
  }
125
- .Field:has(input:focus-visible),
126
- .Field:has(select:focus-visible),
127
- .Field:has(textarea:focus-visible) {
128
- outline: var(--focus-outline);
149
+ .Field:has(:global(input:focus-visible)),
150
+ .Field:has(:global(select:focus-visible)),
151
+ .Field:has(:global(textarea:focus-visible)) {
152
+ outline: var(--focus-ring);
153
+ border-color: var(--focus-ring-color);
129
154
  }
130
- .Field:has(input:focus-visible:user-invalid),
131
- .Field:has(select:focus-visible:user-invalid),
132
- .Field:has(textarea:focus-visible:user-invalid),
133
- .Field.invalid:has(input:focus-visible) {
134
- outline-color: var(--focus-color-error);
155
+ .Field:has(:global(input:focus-visible:user-invalid)),
156
+ .Field:has(:global(select:focus-visible:user-invalid)),
157
+ .Field:has(:global(textarea:focus-visible:user-invalid)) {
158
+ outline-color: var(--focus-ring-color-invalid);
159
+ border-color: var(--focus-ring-color-invalid);
135
160
  }
136
161
  .Field.hasPrefix :global(input) {
137
- padding-inline-start: 0.35em;
162
+ padding-inline-start: var(--space-025);
138
163
  }
139
164
  .Field :global(button) {
140
- margin-right: 2px;
165
+ margin-right: var(--space-025);
141
166
  }
142
167
  .Field :global(button:focus-visible) {
143
168
  outline: var(--focus-outline);
@@ -145,9 +170,9 @@ let {
145
170
  border-radius: calc(var(--field-radius) - 2px);
146
171
  }
147
172
  .Help {
148
- font-size: 0.85em;
149
- color: var(--text-subtle);
150
- line-height: 1.4;
151
- font-weight: 400;
173
+ font-size: min(11px, var(--font-size-075));
174
+ line-height: var(--font-line-height-tight);
175
+ color: var(--text-color-p-subtle);
176
+ font-weight: var(--font-weight-normal);
152
177
  }
153
178
  </style>
@@ -1,16 +1,6 @@
1
- import type { Snippet } from "svelte";
1
+ import { type Snippet } from "svelte";
2
2
  import type { FormField, FormIssue } from "./types.js";
3
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
4
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
5
- $$bindings?: Bindings;
6
- } & Exports;
7
- (internal: unknown, props: Props & {
8
- $$events?: Events;
9
- $$slots?: Slots;
10
- }): Exports;
11
- z_$$bindings?: Bindings;
12
- }
13
- declare const FieldContent: $$__sveltets_2_IsomorphicComponent<{
3
+ type $$ComponentProps = {
14
4
  id: string;
15
5
  contained?: boolean;
16
6
  prefix?: string | Snippet;
@@ -19,13 +9,13 @@ declare const FieldContent: $$__sveltets_2_IsomorphicComponent<{
19
9
  type?: string;
20
10
  label?: string | Snippet;
21
11
  labelTip?: string | Snippet;
22
- direction?: "row" | "column";
12
+ labelHelp?: string | Snippet;
13
+ direction?: 'row' | 'column';
23
14
  required?: boolean;
24
15
  children: Snippet;
25
16
  field?: FormField;
26
17
  issue?: FormIssue;
27
- }, {
28
- [evt: string]: CustomEvent<any>;
29
- }, {}, {}, "">;
30
- type FieldContent = InstanceType<typeof FieldContent>;
18
+ };
19
+ declare const FieldContent: import("svelte").Component<$$ComponentProps, {}, "">;
20
+ type FieldContent = ReturnType<typeof FieldContent>;
31
21
  export default FieldContent;
@@ -1,14 +1,24 @@
1
- <script lang="ts">let {
2
- code,
3
- message
4
- } = $props();
1
+ <script lang="ts">
2
+ /**
3
+ * @description
4
+ * This component is used internally by the Input, Select, etc. components to render the error message.
5
+ */
6
+ let {
7
+ code,
8
+ message
9
+ }: {
10
+ code: string;
11
+ message?: string;
12
+ } = $props();
5
13
  </script>
6
14
 
7
15
  <p class="Error">{message ? message : code}</p>
8
16
 
9
17
  <style>
10
- .Error {
11
- color: var(--text-warn);
18
+ p.Error {
19
+ color: var(--field-color-danger, light-dark(red, red));
12
20
  font-size: max(0.85em, 11px);
21
+ font-weight: var(--font-weight-normal);
22
+ text-wrap: balance;
13
23
  }
14
24
  </style>