storyloco 1.9.3 → 1.10.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
@@ -11,6 +11,7 @@ A collection of slick Storyblok field plugins built with Svelte 5, TypeScript, a
11
11
  - **🎨 Theme** - Color theme selector with visual previews
12
12
  - **🔗 Link** - Link editor with support for internal, external, email, and asset links
13
13
  - **🏗️ Plans** - Floor plan manager with drag-and-drop sorting for types, floors, dimensions, and rooms
14
+ - **📝 Input** - Comprehensive form input field with support for all HTML input types, checkboxes, radio buttons, selects, and textareas
14
15
 
15
16
  ### Vite Plugins
16
17
 
@@ -40,9 +41,10 @@ bun add storyloco
40
41
  import type { Video } from 'storyloco/mux'
41
42
  import type { Heading } from 'storyloco/heading'
42
43
  import type { Link } from 'storyloco/link'
44
+ import type { Input } from 'storyloco/input'
43
45
 
44
46
  // Or import everything
45
- import type { Video, Heading, Link } from 'storyloco'
47
+ import type { Video, Heading, Link, Input } from 'storyloco'
46
48
  ```
47
49
 
48
50
  ### Use Shared Components
@@ -117,6 +119,7 @@ storyloco/
117
119
  │ ├── heading/ # Heading editor plugin
118
120
  │ ├── theme/ # Theme selector plugin
119
121
  │ ├── link/ # Link editor plugin
122
+ │ ├── input/ # Form input field plugin
120
123
  │ └── shared/ # UI component library
121
124
  ├── src/
122
125
  │ └── index.ts # Type exports
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storyloco",
3
- "version": "1.9.3",
3
+ "version": "1.10.0",
4
4
  "description": "A collection of slick Storyblok field plugins built with Svelte 5, TypeScript, and Tailwind CSS",
5
5
  "keywords": [
6
6
  "storyblok",
@@ -27,7 +27,8 @@
27
27
  "packages/theme/types.ts",
28
28
  "packages/shared/dist",
29
29
  "packages/vite/dist",
30
- "packages/ticketsource/types.ts"
30
+ "packages/ticketsource/types.ts",
31
+ "packages/input/types.ts"
31
32
  ],
32
33
  "exports": {
33
34
  ".": {
@@ -47,6 +48,10 @@
47
48
  "types": "./packages/ticketsource/types.ts",
48
49
  "svelte": "./packages/ticketsource/src/app.svelte.ts"
49
50
  },
51
+ "./input": {
52
+ "types": "./packages/input/types.ts",
53
+ "svelte": "./packages/input/src/app.svelte.ts"
54
+ },
50
55
  "./shared": {
51
56
  "types": "./packages/shared/dist/index.d.ts",
52
57
  "svelte": "./packages/shared/dist/index.js"
@@ -0,0 +1,144 @@
1
+ const types = [
2
+ 'text',
3
+ 'email',
4
+ 'number',
5
+ 'tel',
6
+ 'url',
7
+ 'date',
8
+ 'time',
9
+ 'datetime-local',
10
+ 'month',
11
+ 'week',
12
+ 'checkbox',
13
+ 'radio',
14
+ 'select',
15
+ 'textarea',
16
+ 'file',
17
+ 'hidden',
18
+ ] as const
19
+
20
+ namespace Input {
21
+ export type Type = (typeof types)[number]
22
+
23
+ export type Base = {
24
+ name: string
25
+ type: Type
26
+ required: boolean
27
+ disabled: boolean
28
+ value?: string
29
+ }
30
+
31
+ export type Placeholderable = Base & {
32
+ placeholder?: string
33
+ }
34
+
35
+ export type File = Base & {
36
+ type: 'file'
37
+ multiple: boolean
38
+ accept?: string
39
+ }
40
+
41
+ export type Select = Placeholderable & {
42
+ type: 'select'
43
+ options: Array<{ value: string; disabled: boolean; selected: boolean }>
44
+ multiple: boolean
45
+ }
46
+
47
+ export type Checkbox = Omit<Base, 'required' | 'disabled'> & {
48
+ type: 'checkbox'
49
+ options: Array<{ value: string; required: boolean; disabled: boolean; checked: boolean }>
50
+ }
51
+
52
+ export type Radio = Base & {
53
+ type: 'radio'
54
+ options: Array<{ value: string; disabled: boolean; checked: boolean }>
55
+ }
56
+
57
+ export type Text = Placeholderable & {
58
+ type: 'text'
59
+ }
60
+
61
+ export type Email = Placeholderable & {
62
+ type: 'email'
63
+ }
64
+
65
+ export type Number = Placeholderable & {
66
+ type: 'number'
67
+ }
68
+
69
+ export type Tel = Placeholderable & {
70
+ type: 'tel'
71
+ }
72
+
73
+ export type URL = Placeholderable & {
74
+ type: 'url'
75
+ }
76
+
77
+ export type Date = Placeholderable & {
78
+ type: 'date'
79
+ }
80
+
81
+ export type Time = Placeholderable & {
82
+ type: 'time'
83
+ }
84
+
85
+ export type DatetimeLocal = Placeholderable & {
86
+ type: 'datetime-local'
87
+ }
88
+
89
+ export type Month = Placeholderable & {
90
+ type: 'month'
91
+ }
92
+
93
+ export type Week = Placeholderable & {
94
+ type: 'week'
95
+ }
96
+
97
+ export type Textarea = Placeholderable & {
98
+ type: 'textarea'
99
+ }
100
+
101
+ export type Hidden = Base & {
102
+ type: 'hidden'
103
+ }
104
+
105
+ export type Input =
106
+ | File
107
+ | Select
108
+ | Checkbox
109
+ | Radio
110
+ | Text
111
+ | Email
112
+ | Number
113
+ | Tel
114
+ | URL
115
+ | Date
116
+ | Time
117
+ | DatetimeLocal
118
+ | Month
119
+ | Week
120
+ | Textarea
121
+ | Hidden
122
+ }
123
+
124
+ export const types_map = new Map<Input.Type, string>([
125
+ ['text', 'Text'],
126
+ ['email', 'Email'],
127
+ ['number', 'Number'],
128
+ ['tel', 'Telephone'],
129
+ ['url', 'URL'],
130
+ ['date', 'Date'],
131
+ ['time', 'Time'],
132
+ ['datetime-local', 'Datetime Local'],
133
+ ['month', 'Month'],
134
+ ['week', 'Week'],
135
+ ['checkbox', 'Checkbox'],
136
+ ['radio', 'Radio'],
137
+ ['select', 'Select'],
138
+ ['textarea', 'Textarea'],
139
+ ['file', 'File'],
140
+ ['hidden', 'Hidden'],
141
+ ] as const)
142
+
143
+ // convenient re-export to keep existing imports working
144
+ export type Input = Input.Input
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ import { Checkbox as CheckboxPrimitive } from "bits-ui";
3
+ import CheckIcon from "@lucide/svelte/icons/check";
4
+ import MinusIcon from "@lucide/svelte/icons/minus";
5
+ import { cn, type WithoutChildrenOrChild } from "../../../utils.js";
6
+
7
+ let {
8
+ ref = $bindable(null),
9
+ checked = $bindable(false),
10
+ indeterminate = $bindable(false),
11
+ class: className,
12
+ ...restProps
13
+ }: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
14
+ </script>
15
+
16
+ <CheckboxPrimitive.Root
17
+ bind:ref
18
+ data-slot="checkbox"
19
+ class={cn(
20
+ "border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive shadow-xs peer flex size-4 shrink-0 items-center justify-center rounded-[4px] border outline-none transition-shadow focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
21
+ className
22
+ )}
23
+ bind:checked
24
+ bind:indeterminate
25
+ {...restProps}
26
+ >
27
+ {#snippet children({ checked, indeterminate })}
28
+ <div data-slot="checkbox-indicator" class="text-current transition-none">
29
+ {#if checked}
30
+ <CheckIcon class="size-3.5" />
31
+ {:else if indeterminate}
32
+ <MinusIcon class="size-3.5" />
33
+ {/if}
34
+ </div>
35
+ {/snippet}
36
+ </CheckboxPrimitive.Root>
@@ -0,0 +1,4 @@
1
+ import { Checkbox as CheckboxPrimitive } from "bits-ui";
2
+ declare const Checkbox: import("svelte").Component<Omit<Omit<CheckboxPrimitive.RootProps, "child">, "children">, {}, "ref" | "checked" | "indeterminate">;
3
+ type Checkbox = ReturnType<typeof Checkbox>;
4
+ export default Checkbox;
@@ -0,0 +1,2 @@
1
+ import Root from "./checkbox.svelte";
2
+ export { Root, Root as Checkbox, };
@@ -0,0 +1,4 @@
1
+ import Root from "./checkbox.svelte";
2
+ export { Root,
3
+ //
4
+ Root as Checkbox, };
@@ -0,0 +1,3 @@
1
+ import Root from "./radio-group.svelte";
2
+ import Item from "./radio-group-item.svelte";
3
+ export { Root, Item, Root as RadioGroup, Item as RadioGroupItem, };
@@ -0,0 +1,5 @@
1
+ import Root from "./radio-group.svelte";
2
+ import Item from "./radio-group-item.svelte";
3
+ export { Root, Item,
4
+ //
5
+ Root as RadioGroup, Item as RadioGroupItem, };
@@ -0,0 +1,31 @@
1
+ <script lang="ts">
2
+ import { RadioGroup as RadioGroupPrimitive } from "bits-ui";
3
+ import CircleIcon from "@lucide/svelte/icons/circle";
4
+ import { cn, type WithoutChildrenOrChild } from "../../../utils.js";
5
+
6
+ let {
7
+ ref = $bindable(null),
8
+ class: className,
9
+ ...restProps
10
+ }: WithoutChildrenOrChild<RadioGroupPrimitive.ItemProps> = $props();
11
+ </script>
12
+
13
+ <RadioGroupPrimitive.Item
14
+ bind:ref
15
+ data-slot="radio-group-item"
16
+ class={cn(
17
+ "border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 shadow-xs aspect-square size-4 shrink-0 rounded-full border outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
18
+ className
19
+ )}
20
+ {...restProps}
21
+ >
22
+ {#snippet children({ checked })}
23
+ <div data-slot="radio-group-indicator" class="relative flex items-center justify-center">
24
+ {#if checked}
25
+ <CircleIcon
26
+ class="fill-primary absolute left-1/2 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2"
27
+ />
28
+ {/if}
29
+ </div>
30
+ {/snippet}
31
+ </RadioGroupPrimitive.Item>
@@ -0,0 +1,4 @@
1
+ import { RadioGroup as RadioGroupPrimitive } from "bits-ui";
2
+ declare const RadioGroupItem: import("svelte").Component<Omit<Omit<RadioGroupPrimitive.ItemProps, "child">, "children">, {}, "ref">;
3
+ type RadioGroupItem = ReturnType<typeof RadioGroupItem>;
4
+ export default RadioGroupItem;
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import { RadioGroup as RadioGroupPrimitive } from "bits-ui";
3
+ import { cn } from "../../../utils.js";
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ value = $bindable(""),
9
+ ...restProps
10
+ }: RadioGroupPrimitive.RootProps = $props();
11
+ </script>
12
+
13
+ <RadioGroupPrimitive.Root
14
+ bind:ref
15
+ bind:value
16
+ data-slot="radio-group"
17
+ class={cn("grid gap-3", className)}
18
+ {...restProps}
19
+ />
@@ -0,0 +1,4 @@
1
+ import { RadioGroup as RadioGroupPrimitive } from "bits-ui";
2
+ declare const RadioGroup: import("svelte").Component<RadioGroupPrimitive.RootProps, {}, "value" | "ref">;
3
+ type RadioGroup = ReturnType<typeof RadioGroup>;
4
+ export default RadioGroup;
@@ -0,0 +1,2 @@
1
+ import Root from "./textarea.svelte";
2
+ export { Root, Root as Textarea, };
@@ -0,0 +1,4 @@
1
+ import Root from "./textarea.svelte";
2
+ export { Root,
3
+ //
4
+ Root as Textarea, };
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ import { cn, type WithElementRef, type WithoutChildren } from '../../../utils.js'
3
+ import type { HTMLTextareaAttributes } from 'svelte/elements'
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ value = $bindable(),
8
+ class: className,
9
+ ...restProps
10
+ }: WithoutChildren<WithElementRef<HTMLTextareaAttributes>> = $props()
11
+ </script>
12
+
13
+ <textarea
14
+ bind:this={ref}
15
+ data-slot="textarea"
16
+ class={cn(
17
+ 'border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input-background field-sizing-content shadow-xs flex min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
18
+ className
19
+ )}
20
+ bind:value
21
+ {...restProps}
22
+ ></textarea>
@@ -0,0 +1,5 @@
1
+ import { type WithElementRef } from '../../../utils.js';
2
+ import type { HTMLTextareaAttributes } from 'svelte/elements';
3
+ declare const Textarea: import("svelte").Component<Omit<WithElementRef<HTMLTextareaAttributes>, "children">, {}, "value" | "ref">;
4
+ type Textarea = ReturnType<typeof Textarea>;
5
+ export default Textarea;
@@ -1,11 +1,14 @@
1
1
  export * as Accordion from './components/ui/accordion/index.js';
2
2
  export { Button } from './components/ui/button/index.js';
3
3
  export * as Card from './components/ui/card/index.js';
4
+ export { Checkbox } from './components/ui/checkbox/index.js';
4
5
  export { Input } from './components/ui/input/index.js';
5
6
  export { Label } from './components/ui/label/index.js';
7
+ export * as RadioGroup from './components/ui/radio-group/index.js';
6
8
  export * as Select from './components/ui/select/index.js';
7
9
  export { Separator } from './components/ui/separator/index.js';
8
10
  export { Skeleton } from './components/ui/skeleton/index.js';
9
11
  export { Switch } from './components/ui/switch/index.js';
12
+ export { Textarea } from './components/ui/textarea/index.js';
10
13
  export * as Tabs from './components/ui/tabs/index.js';
11
14
  export { setup } from './setup.js';
@@ -2,12 +2,15 @@
2
2
  export * as Accordion from './components/ui/accordion/index.js';
3
3
  export { Button } from './components/ui/button/index.js';
4
4
  export * as Card from './components/ui/card/index.js';
5
+ export { Checkbox } from './components/ui/checkbox/index.js';
5
6
  export { Input } from './components/ui/input/index.js';
6
7
  export { Label } from './components/ui/label/index.js';
8
+ export * as RadioGroup from './components/ui/radio-group/index.js';
7
9
  export * as Select from './components/ui/select/index.js';
8
10
  export { Separator } from './components/ui/separator/index.js';
9
11
  export { Skeleton } from './components/ui/skeleton/index.js';
10
12
  export { Switch } from './components/ui/switch/index.js';
13
+ export { Textarea } from './components/ui/textarea/index.js';
11
14
  export * as Tabs from './components/ui/tabs/index.js';
12
15
  // Global
13
16
  export { setup } from './setup.js';
@@ -1,6 +1,5 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
- import { format_date, format_elapse } from 'kitto';
4
3
  export function cn(...inputs) {
5
4
  return twMerge(clsx(inputs));
6
5
  }