@r2digisolutions/ui 0.23.0 → 0.24.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.
@@ -27,4 +27,5 @@ import DialogTitle from './ui/Dialog/DialogTitle.svelte';
27
27
  import DialogDescription from './ui/Dialog/DialogDescription.svelte';
28
28
  import DialogContent from './ui/Dialog/DialogContent.svelte';
29
29
  import DialogFooter from './ui/Dialog/DialogFooter.svelte';
30
- export { Dialog, DialogHeader, DialogTitle, DialogDescription, DialogContent, DialogFooter, Tag, NoContent, Alert, Avatar, Button, Badge, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Container, Checkbox, Field, Section, Loading, TableList, Heading, Label, Input, InputRadio, Textarea, };
30
+ import Selector from './ui/Selector/Selector.svelte';
31
+ export { Selector, Dialog, DialogHeader, DialogTitle, DialogDescription, DialogContent, DialogFooter, Tag, NoContent, Alert, Avatar, Button, Badge, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Container, Checkbox, Field, Section, Loading, TableList, Heading, Label, Input, InputRadio, Textarea, };
@@ -27,4 +27,5 @@ import DialogTitle from './ui/Dialog/DialogTitle.svelte';
27
27
  import DialogDescription from './ui/Dialog/DialogDescription.svelte';
28
28
  import DialogContent from './ui/Dialog/DialogContent.svelte';
29
29
  import DialogFooter from './ui/Dialog/DialogFooter.svelte';
30
- export { Dialog, DialogHeader, DialogTitle, DialogDescription, DialogContent, DialogFooter, Tag, NoContent, Alert, Avatar, Button, Badge, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Container, Checkbox, Field, Section, Loading, TableList, Heading, Label, Input, InputRadio, Textarea, };
30
+ import Selector from './ui/Selector/Selector.svelte';
31
+ export { Selector, Dialog, DialogHeader, DialogTitle, DialogDescription, DialogContent, DialogFooter, Tag, NoContent, Alert, Avatar, Button, Badge, Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Container, Checkbox, Field, Section, Loading, TableList, Heading, Label, Input, InputRadio, Textarea, };
@@ -0,0 +1,102 @@
1
+ <script lang="ts" generics="M extends string">
2
+ interface ModeOption<M extends string> {
3
+ id: M;
4
+ label: string;
5
+ icon?: any;
6
+ disabled?: boolean;
7
+ tooltip?: string;
8
+ }
9
+
10
+ interface Props<M extends string> {
11
+ modes: ModeOption<M>[];
12
+ currentMode: M; // bindable
13
+ onModeChange?: (m: M) => void;
14
+ activation?: 'auto' | 'manual';
15
+ }
16
+
17
+ let {
18
+ modes,
19
+ currentMode = $bindable<M>(),
20
+ onModeChange,
21
+ activation = 'auto'
22
+ }: Props<M> = $props();
23
+
24
+ const buttons = new Map<M, HTMLButtonElement>();
25
+
26
+ function focusActive() {
27
+ const el = buttons.get(currentMode);
28
+ queueMicrotask(() => el?.focus());
29
+ }
30
+
31
+ function change(m: M) {
32
+ if (m === currentMode) return;
33
+ currentMode = m;
34
+ onModeChange?.(m);
35
+ focusActive();
36
+ }
37
+
38
+ function onKeydown(e: KeyboardEvent) {
39
+ const horiz = e.key === 'ArrowLeft' || e.key === 'ArrowRight';
40
+ const vert = e.key === 'ArrowUp' || e.key === 'ArrowDown';
41
+ const home = e.key === 'Home';
42
+ const end = e.key === 'End';
43
+
44
+ if (!horiz && !vert && !home && !end) return;
45
+
46
+ e.preventDefault();
47
+ const enabled = modes.filter((m) => !m.disabled);
48
+ if (enabled.length === 0) return;
49
+
50
+ const curIdx = enabled.findIndex((m) => m.id === currentMode);
51
+ const idx = curIdx === -1 ? 0 : curIdx;
52
+
53
+ if (home) return change(enabled[0].id);
54
+ if (end) return change(enabled[enabled.length - 1].id);
55
+
56
+ const dir = e.key === 'ArrowRight' || e.key === 'ArrowDown' ? 1 : -1;
57
+ const nextIndex = (idx + dir + enabled.length) % enabled.length;
58
+ change(enabled[nextIndex].id);
59
+ }
60
+ </script>
61
+
62
+ <div
63
+ class="flex rounded-lg bg-gray-100 p-1"
64
+ role="tablist"
65
+ aria-label="Seleccionar vista"
66
+ aria-orientation="horizontal"
67
+ onkeydown={onKeydown}
68
+ tabindex="0"
69
+ >
70
+ {#each modes as m (m.id)}
71
+ <button
72
+ bind:this={
73
+ () => buttons.get(m.id),
74
+ (el) => {
75
+ if (el) buttons.set(m.id, el);
76
+ }
77
+ }
78
+ type="button"
79
+ role="tab"
80
+ aria-selected={currentMode === m.id}
81
+ aria-controls={undefined}
82
+ disabled={m.disabled}
83
+ tabindex={currentMode === m.id ? 0 : -1}
84
+ onfocus={() => {
85
+ if (activation === 'auto' && !m.disabled && currentMode !== m.id) {
86
+ change(m.id);
87
+ }
88
+ }}
89
+ onclick={() => !m.disabled && change(m.id)}
90
+ class={`flex items-center space-x-1 rounded-md px-3 py-2 text-sm font-medium transition-all
91
+ ${currentMode === m.id ? 'bg-white text-purple-600 shadow-sm' : 'text-gray-600 hover:bg-gray-50 hover:text-gray-900'}
92
+ ${m.disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}
93
+ focus:outline-none focus-visible:ring-2 focus-visible:ring-purple-500 focus-visible:ring-offset-1`}
94
+ title={m.tooltip ?? m.label}
95
+ >
96
+ {#if m.icon}
97
+ <m.icon class="h-4 w-4" />
98
+ {/if}
99
+ <span class="hidden sm:inline">{m.label}</span>
100
+ </button>
101
+ {/each}
102
+ </div>
@@ -0,0 +1,37 @@
1
+ interface ModeOption<M extends string> {
2
+ id: M;
3
+ label: string;
4
+ icon?: any;
5
+ disabled?: boolean;
6
+ tooltip?: string;
7
+ }
8
+ interface Props<M extends string> {
9
+ modes: ModeOption<M>[];
10
+ currentMode: M;
11
+ onModeChange?: (m: M) => void;
12
+ activation?: 'auto' | 'manual';
13
+ }
14
+ declare function $$render<M extends string>(): {
15
+ props: Props<M>;
16
+ exports: {};
17
+ bindings: "currentMode";
18
+ slots: {};
19
+ events: {};
20
+ };
21
+ declare class __sveltets_Render<M extends string> {
22
+ props(): ReturnType<typeof $$render<M>>['props'];
23
+ events(): ReturnType<typeof $$render<M>>['events'];
24
+ slots(): ReturnType<typeof $$render<M>>['slots'];
25
+ bindings(): "currentMode";
26
+ exports(): {};
27
+ }
28
+ interface $$IsomorphicComponent {
29
+ new <M extends string>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<M>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<M>['props']>, ReturnType<__sveltets_Render<M>['events']>, ReturnType<__sveltets_Render<M>['slots']>> & {
30
+ $$bindings?: ReturnType<__sveltets_Render<M>['bindings']>;
31
+ } & ReturnType<__sveltets_Render<M>['exports']>;
32
+ <M extends string>(internal: unknown, props: ReturnType<__sveltets_Render<M>['props']> & {}): ReturnType<__sveltets_Render<M>['exports']>;
33
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
34
+ }
35
+ declare const Selector: $$IsomorphicComponent;
36
+ type Selector<M extends string> = InstanceType<typeof Selector<M>>;
37
+ export default Selector;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@r2digisolutions/ui",
3
- "version": "0.23.0",
3
+ "version": "0.24.0",
4
4
  "private": false,
5
5
  "packageManager": "bun@1.2.23",
6
6
  "publishConfig": {