@viniaraujo68/plinth 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -322,6 +322,9 @@ date fields, the pair is `YYYY-MM-DD`, and an empty end leaves that side open, s
322
322
  "all time" are pairs too. Presets can follow the calendar instead of a duration — `thisMonth`,
323
323
  `lastMonth`, `lastMonths(n)` and `allTime` build the usual ones, and any `range(now)` function will
324
324
  do. Every preset re-anchors on a timer, and a picker handed a pair opens on the preset that names it.
325
+ `caption` puts visible text before the presets, as on `SegmentedControl`, and `size` (`sm` or `md`)
326
+ sizes the presets and the typed fields together, so the fields line up with the buttons.
327
+ `fieldLabels` puts the field labels `"above"` their fields (the default) or `"beside"` them.
325
328
 
326
329
  `JsonInput` edits a JSON document as text: it reports through a bindable `invalid` whether the text
327
330
  parses, shows the parser's message after the first blur, can reindent on blur, and sets the
@@ -63,6 +63,21 @@
63
63
  toLabel?: string;
64
64
  /** Shown, as an alert, while the typed pair is out of order. */
65
65
  invalidRangeLabel?: string;
66
+ /**
67
+ * Visible text before the presets — "Period:". Passed to the {@link SegmentedControl}, so it
68
+ * sits on the preset row; `label` stays the accessible name.
69
+ */
70
+ caption?: string;
71
+ /**
72
+ * Sizes the presets and the custom fields together, so the fields line up with the buttons.
73
+ * `sm` is for a toolbar or a card header, where the default height would dominate.
74
+ */
75
+ size?: "sm" | "md";
76
+ /**
77
+ * Where the custom fields' labels sit: `"above"` stacks each one over its field, `"beside"`
78
+ * puts it before the field on the same line, so the whole picker can stay one row.
79
+ */
80
+ fieldLabels?: "above" | "beside";
66
81
  onchange?: (value: DateRange) => void;
67
82
  }
68
83
 
@@ -78,6 +93,9 @@
78
93
  fromLabel = "From",
79
94
  toLabel = "To",
80
95
  invalidRangeLabel = "The start must not be after the end.",
96
+ caption,
97
+ size = "md",
98
+ fieldLabels = "above",
81
99
  onchange,
82
100
  }: Props = $props();
83
101
 
@@ -106,6 +124,9 @@
106
124
 
107
125
  const isCustom = $derived(selection === CUSTOM_PRESET_ID);
108
126
  const days = $derived(mode === "date");
127
+ const fieldWrapper = $derived(
128
+ fieldLabels === "beside" ? "flex items-center gap-2" : "flex flex-col gap-1",
129
+ );
109
130
 
110
131
  const options = $derived([
111
132
  ...presets.map(({ id, label }) => ({ id, label })),
@@ -251,18 +272,18 @@ buttons are labelled by the list itself, through `DateRangePreset.label`.
251
272
  ```
252
273
  -->
253
274
 
254
- <div class={["flex flex-wrap items-end gap-x-4 gap-y-3", cls]}>
275
+ <div class={["flex flex-wrap items-end gap-x-4 gap-y-3", cls]} data-size={size}>
255
276
  <!-- A segmented control rather than a joined row: a calendar picker easily offers six windows,
256
277
  and a joined row cannot wrap onto a second line at phone width. -->
257
- <SegmentedControl {options} value={selection} {label} onchange={pick} />
278
+ <SegmentedControl {options} value={selection} {label} {caption} {size} onchange={pick} />
258
279
 
259
280
  {#if isCustom}
260
281
  <div class="flex flex-wrap items-end gap-x-4 gap-y-3">
261
- <div class="flex flex-col gap-1">
282
+ <div class={fieldWrapper}>
262
283
  <label class="label text-xs" for={fromId}>{fromLabel}</label>
263
284
  <input
264
285
  id={fromId}
265
- class="input min-h-11"
286
+ class="plinth-range-field input"
266
287
  class:input-error={rangeError !== null}
267
288
  type={days ? "date" : "datetime-local"}
268
289
  value={customFrom}
@@ -276,11 +297,11 @@ buttons are labelled by the list itself, through `DateRangePreset.label`.
276
297
  />
277
298
  </div>
278
299
 
279
- <div class="flex flex-col gap-1">
300
+ <div class={fieldWrapper}>
280
301
  <label class="label text-xs" for={toId}>{toLabel}</label>
281
302
  <input
282
303
  id={toId}
283
- class="input min-h-11"
304
+ class="plinth-range-field input"
284
305
  class:input-error={rangeError !== null}
285
306
  type={days ? "date" : "datetime-local"}
286
307
  value={customTo}
@@ -300,3 +321,28 @@ buttons are labelled by the list itself, through `DateRangePreset.label`.
300
321
  <p id={errorId} class="basis-full text-sm text-error" role="alert">{rangeError}</p>
301
322
  {/if}
302
323
  </div>
324
+
325
+ <style>
326
+ /* Chrome sizes a date field to its text alone, leaving no room for the padding and the picker
327
+ icon, which then covers the last digit. */
328
+ .plinth-range-field {
329
+ height: 2rem;
330
+ min-width: 9rem;
331
+ font-size: 0.78rem;
332
+ }
333
+
334
+ .plinth-range-field[type="datetime-local"] {
335
+ min-width: 12.5rem;
336
+ }
337
+
338
+ [data-size="sm"] .plinth-range-field {
339
+ height: 1.625rem;
340
+ font-size: 0.7rem;
341
+ }
342
+
343
+ @media (max-width: 35rem) {
344
+ [data-size="md"] .plinth-range-field {
345
+ height: 2.5rem;
346
+ }
347
+ }
348
+ </style>
@@ -44,6 +44,21 @@ interface Props {
44
44
  toLabel?: string;
45
45
  /** Shown, as an alert, while the typed pair is out of order. */
46
46
  invalidRangeLabel?: string;
47
+ /**
48
+ * Visible text before the presets — "Period:". Passed to the {@link SegmentedControl}, so it
49
+ * sits on the preset row; `label` stays the accessible name.
50
+ */
51
+ caption?: string;
52
+ /**
53
+ * Sizes the presets and the custom fields together, so the fields line up with the buttons.
54
+ * `sm` is for a toolbar or a card header, where the default height would dominate.
55
+ */
56
+ size?: "sm" | "md";
57
+ /**
58
+ * Where the custom fields' labels sit: `"above"` stacks each one over its field, `"beside"`
59
+ * puts it before the field on the same line, so the whole picker can stay one row.
60
+ */
61
+ fieldLabels?: "above" | "beside";
47
62
  onchange?: (value: DateRange) => void;
48
63
  }
49
64
  /**
package/dist/index.d.ts CHANGED
@@ -5,6 +5,6 @@
5
5
  * no portable way to import its own manifest, and a consumer that only wants to log a version
6
6
  * should not have to bundle one. `version.spec.ts` fails when this drifts from the manifest.
7
7
  */
8
- export declare const LIBRARY_VERSION = "0.6.0";
8
+ export declare const LIBRARY_VERSION = "0.7.0";
9
9
  export { AsyncAction, type AsyncActionStatus, type AsyncFn } from "./async-action.svelte.js";
10
10
  export { reportError, setErrorReporter, type ErrorReporter } from "./error.js";
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  * no portable way to import its own manifest, and a consumer that only wants to log a version
6
6
  * should not have to bundle one. `version.spec.ts` fails when this drifts from the manifest.
7
7
  */
8
- export const LIBRARY_VERSION = "0.6.0";
8
+ export const LIBRARY_VERSION = "0.7.0";
9
9
  // The root entry carries only what is not tied to one area: the error channel an app installs
10
10
  // once, and the async state machine the components are built on. Everything visual is reached
11
11
  // through a subpath — `/theme`, `/attachments`, `/components`, `/toast` — so importing a button
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viniaraujo68/plinth",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "A personal Svelte 5 design system: theme, application shell, interface primitives, routing metadata, a fetch wrapper and locale-aware formatters.",
5
5
  "license": "MIT",
6
6
  "type": "module",