@okaapp/oka-ui-sv 0.2.1 → 0.3.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 +3 -0
- package/dist/components/core/dialog/Dialog.svelte +12 -1
- package/dist/components/core/dialog/Dialog.svelte.d.ts +1 -0
- package/dist/components/core/dialog/dialog.css +22 -2
- package/dist/components/core/input/Input.svelte +5 -1
- package/dist/components/core/input/Input.svelte.d.ts +4 -1
- package/dist/components/core/input/input.css +0 -1
- package/dist/components/core/pin-input/PinInput.svelte +38 -0
- package/dist/components/core/pin-input/PinInput.svelte.d.ts +5 -0
- package/dist/components/core/pin-input/pin-input.css +103 -0
- package/dist/components/core/tooltips/Tooltips.svelte +28 -0
- package/dist/components/core/tooltips/Tooltips.svelte.d.ts +9 -25
- package/dist/components/core/tooltips/tooltips.css +37 -0
- package/dist/components/styling/oka-style-provider/OKAStyleProvider.svelte +4 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -76,12 +76,15 @@ OKA UI comes with several built-in themes:
|
|
|
76
76
|
- Badge
|
|
77
77
|
- Button
|
|
78
78
|
- Checkbox
|
|
79
|
+
- Dialog
|
|
79
80
|
- Input
|
|
80
81
|
- Loading
|
|
81
82
|
- Pagination
|
|
83
|
+
- PinInput
|
|
82
84
|
- Select (Single & Multi)
|
|
83
85
|
- Separator
|
|
84
86
|
- Sidebar
|
|
87
|
+
- Tooltips
|
|
85
88
|
|
|
86
89
|
### Usage Example
|
|
87
90
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
description?: Snippet;
|
|
13
13
|
contentProps?: WithoutChild<Dialog.ContentProps>;
|
|
14
14
|
actionButtons?: Snippet;
|
|
15
|
+
size?: "sm" | "md" | "lg";
|
|
15
16
|
};
|
|
16
17
|
|
|
17
18
|
let {
|
|
@@ -23,8 +24,15 @@
|
|
|
23
24
|
subtitle,
|
|
24
25
|
description,
|
|
25
26
|
actionButtons,
|
|
27
|
+
size = "md",
|
|
26
28
|
...restProps
|
|
27
29
|
}: Props = $props();
|
|
30
|
+
|
|
31
|
+
const sizeClass = {
|
|
32
|
+
sm: "dialog-content--sm",
|
|
33
|
+
md: "dialog-content--md",
|
|
34
|
+
lg: "dialog-content--lg",
|
|
35
|
+
};
|
|
28
36
|
</script>
|
|
29
37
|
|
|
30
38
|
<Dialog.Root bind:open {...restProps}>
|
|
@@ -33,7 +41,10 @@
|
|
|
33
41
|
</Dialog.Trigger>
|
|
34
42
|
<Dialog.Portal>
|
|
35
43
|
<Dialog.Overlay class="dialog-overlay" />
|
|
36
|
-
<Dialog.Content
|
|
44
|
+
<Dialog.Content
|
|
45
|
+
{...contentProps}
|
|
46
|
+
class={`dialog-content ${sizeClass[size]}`}
|
|
47
|
+
>
|
|
37
48
|
<div class="dialog-topbar">
|
|
38
49
|
<div class="dialog-topbar-content">
|
|
39
50
|
<Dialog.Title class="dialog-title">
|
|
@@ -8,6 +8,7 @@ type Props = Dialog.RootProps & {
|
|
|
8
8
|
description?: Snippet;
|
|
9
9
|
contentProps?: WithoutChild<Dialog.ContentProps>;
|
|
10
10
|
actionButtons?: Snippet;
|
|
11
|
+
size?: "sm" | "md" | "lg";
|
|
11
12
|
};
|
|
12
13
|
declare const Dialog: import("svelte").Component<Props, {}, "open">;
|
|
13
14
|
type Dialog = ReturnType<typeof Dialog>;
|
|
@@ -21,11 +21,32 @@
|
|
|
21
21
|
width: fit-content;
|
|
22
22
|
max-width: 800px;
|
|
23
23
|
min-width: 480px;
|
|
24
|
+
max-height: calc(100vh - 48px);
|
|
24
25
|
border-radius: 12px;
|
|
25
26
|
background-color: var(--surface-primary);
|
|
26
27
|
transform: translate(-50%, -50%);
|
|
27
28
|
outline: none;
|
|
28
29
|
overflow: clip;
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.dialog-content--sm {
|
|
35
|
+
width: 480px;
|
|
36
|
+
min-width: 480px;
|
|
37
|
+
max-width: 480px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.dialog-content--md {
|
|
41
|
+
width: 600px;
|
|
42
|
+
min-width: 600px;
|
|
43
|
+
max-width: 600px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.dialog-content--lg {
|
|
47
|
+
width: 800px;
|
|
48
|
+
min-width: 800px;
|
|
49
|
+
max-width: 800px;
|
|
29
50
|
}
|
|
30
51
|
|
|
31
52
|
.dialog-content[data-state="open"] {
|
|
@@ -83,9 +104,8 @@
|
|
|
83
104
|
.dialog-body {
|
|
84
105
|
display: flex;
|
|
85
106
|
flex-direction: column;
|
|
86
|
-
width:
|
|
107
|
+
width: 100%;
|
|
87
108
|
min-width: 480px;
|
|
88
|
-
max-width: 480px;
|
|
89
109
|
padding: 16px;
|
|
90
110
|
gap: 16px;
|
|
91
111
|
}
|
|
@@ -17,9 +17,12 @@
|
|
|
17
17
|
placeholder = "Nhập vào đây",
|
|
18
18
|
ref = $bindable(null),
|
|
19
19
|
value = $bindable(),
|
|
20
|
+
invalid = $bindable(false),
|
|
20
21
|
class: className,
|
|
21
22
|
...restProps
|
|
22
|
-
}: Props
|
|
23
|
+
}: Props & {
|
|
24
|
+
invalid?: boolean;
|
|
25
|
+
} = $props();
|
|
23
26
|
</script>
|
|
24
27
|
|
|
25
28
|
<input
|
|
@@ -27,6 +30,7 @@
|
|
|
27
30
|
bind:this={ref}
|
|
28
31
|
data-slot="input"
|
|
29
32
|
class="input focus-override"
|
|
33
|
+
class:input--invalid={invalid}
|
|
30
34
|
style="font: inherit;"
|
|
31
35
|
bind:value
|
|
32
36
|
{...restProps}
|
|
@@ -9,6 +9,9 @@ type Props = WithElementRef<Omit<HTMLInputAttributes, "type"> & ({
|
|
|
9
9
|
type?: InputType;
|
|
10
10
|
files?: undefined;
|
|
11
11
|
})>;
|
|
12
|
-
|
|
12
|
+
type $$ComponentProps = Props & {
|
|
13
|
+
invalid?: boolean;
|
|
14
|
+
};
|
|
15
|
+
declare const Input: import("svelte").Component<$$ComponentProps, {}, "ref" | "value" | "invalid">;
|
|
13
16
|
type Input = ReturnType<typeof Input>;
|
|
14
17
|
export default Input;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import "./pin-input.css";
|
|
3
|
+
import { PinInput, type WithoutChildrenOrChild } from "bits-ui";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
ref = $bindable(null),
|
|
7
|
+
value = $bindable(""),
|
|
8
|
+
maxlength = 6,
|
|
9
|
+
disabled = false,
|
|
10
|
+
...props
|
|
11
|
+
}: WithoutChildrenOrChild<PinInput.RootProps> = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<PinInput.Root
|
|
15
|
+
{maxlength}
|
|
16
|
+
bind:value
|
|
17
|
+
bind:ref
|
|
18
|
+
{disabled}
|
|
19
|
+
class={`pin-input-root ${disabled ? "pin-input--disabled" : ""}`}
|
|
20
|
+
{...props}
|
|
21
|
+
>
|
|
22
|
+
{#snippet children({ cells })}
|
|
23
|
+
<div class="pin-input">
|
|
24
|
+
{#each cells as cell, i (i)}
|
|
25
|
+
<PinInput.Cell {cell} class="pin-input__cell">
|
|
26
|
+
{#if cell.char !== null}
|
|
27
|
+
<div class="pin-input__char">
|
|
28
|
+
{cell.char}
|
|
29
|
+
</div>
|
|
30
|
+
{/if}
|
|
31
|
+
{#if cell.hasFakeCaret}
|
|
32
|
+
<div class="pin-input__caret"></div>
|
|
33
|
+
{/if}
|
|
34
|
+
</PinInput.Cell>
|
|
35
|
+
{/each}
|
|
36
|
+
</div>
|
|
37
|
+
{/snippet}
|
|
38
|
+
</PinInput.Root>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
.pin-input {
|
|
2
|
+
display: flex;
|
|
3
|
+
gap: 8px;
|
|
4
|
+
align-items: center;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.pin-input--disabled {
|
|
8
|
+
opacity: 0.5;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.pin-input__cell {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
justify-content: center;
|
|
16
|
+
width: 48px;
|
|
17
|
+
height: 48px;
|
|
18
|
+
font-size: 20px;
|
|
19
|
+
font-weight: 600;
|
|
20
|
+
border: 2px solid var(--stroke-light);
|
|
21
|
+
background-color: var(--surface-primary);
|
|
22
|
+
color: var(--content-primary);
|
|
23
|
+
border-radius: 12px;
|
|
24
|
+
transition: all 300ms ease;
|
|
25
|
+
outline: none;
|
|
26
|
+
cursor: text;
|
|
27
|
+
position: relative;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.pin-input .pin-input__cell:hover {
|
|
31
|
+
border-color: var(--stroke-medium) !important;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.pin-input__cell:hover {
|
|
35
|
+
border-color: var(--stroke-medium) !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.pin-input__cell[data-active] {
|
|
39
|
+
border-color: var(--accent-primary);
|
|
40
|
+
background-color: var(--surface-secondary);
|
|
41
|
+
box-shadow: 0 0 0 3px rgba(var(--accent-primary-rgb), 0.1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.pin-input__cell[data-inactive] {
|
|
45
|
+
border-color: var(--stroke-light);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Caret animation for the active cell */
|
|
49
|
+
.pin-input__caret {
|
|
50
|
+
position: absolute;
|
|
51
|
+
width: 2px;
|
|
52
|
+
height: 24px;
|
|
53
|
+
background-color: var(--accent-primary);
|
|
54
|
+
animation: caret-blink 1s ease-in-out infinite;
|
|
55
|
+
pointer-events: none;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@keyframes caret-blink {
|
|
59
|
+
|
|
60
|
+
0%,
|
|
61
|
+
49% {
|
|
62
|
+
opacity: 1;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
50%,
|
|
66
|
+
100% {
|
|
67
|
+
opacity: 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Root container adjustments */
|
|
72
|
+
.pin-input-root {
|
|
73
|
+
display: flex;
|
|
74
|
+
gap: 8px;
|
|
75
|
+
position: relative;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.pin-input-root[disabled] .pin-input__cell {
|
|
79
|
+
background-color: var(--surface-tertiary);
|
|
80
|
+
border-color: var(--stroke-muted);
|
|
81
|
+
color: var(--content-tertiary);
|
|
82
|
+
cursor: not-allowed;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.pin-input-root[disabled] .pin-input__cell:hover {
|
|
86
|
+
border-color: var(--stroke-muted);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Text character styling */
|
|
90
|
+
.pin-input__char {
|
|
91
|
+
display: flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
justify-content: center;
|
|
94
|
+
width: 100%;
|
|
95
|
+
height: 100%;
|
|
96
|
+
font-variant: tabular-nums;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Focus visible state */
|
|
100
|
+
.pin-input__cell:focus-visible {
|
|
101
|
+
outline: 2px solid var(--accent-primary);
|
|
102
|
+
outline-offset: 2px;
|
|
103
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import "./tooltips.css";
|
|
3
|
+
import { Tooltip } from "bits-ui";
|
|
4
|
+
import type { Snippet } from "svelte";
|
|
5
|
+
|
|
6
|
+
let {
|
|
7
|
+
children,
|
|
8
|
+
trigger,
|
|
9
|
+
delayDuration = 200,
|
|
10
|
+
...props
|
|
11
|
+
}: Tooltip.RootProps & {
|
|
12
|
+
trigger: Snippet;
|
|
13
|
+
children: Snippet;
|
|
14
|
+
} = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<Tooltip.Provider delayDuration={200}>
|
|
18
|
+
<Tooltip.Root {delayDuration} {...props}>
|
|
19
|
+
<Tooltip.Trigger class="tooltip-trigger">
|
|
20
|
+
{@render trigger()}
|
|
21
|
+
</Tooltip.Trigger>
|
|
22
|
+
<Tooltip.Portal>
|
|
23
|
+
<Tooltip.Content class="tooltip-content" sideOffset={8}>
|
|
24
|
+
{@render children()}
|
|
25
|
+
</Tooltip.Content>
|
|
26
|
+
</Tooltip.Portal>
|
|
27
|
+
</Tooltip.Root>
|
|
28
|
+
</Tooltip.Provider>
|
|
@@ -1,26 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
$$bindings?: string | undefined;
|
|
1
|
+
import "./tooltips.css";
|
|
2
|
+
import { Tooltip } from "bits-ui";
|
|
3
|
+
import type { Snippet } from "svelte";
|
|
4
|
+
type $$ComponentProps = Tooltip.RootProps & {
|
|
5
|
+
trigger: Snippet;
|
|
6
|
+
children: Snippet;
|
|
8
7
|
};
|
|
9
|
-
declare const Tooltips:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
[evt: string]: CustomEvent<any>;
|
|
13
|
-
}, {}, {}, string>;
|
|
14
|
-
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> {
|
|
15
|
-
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
-
$$bindings?: Bindings;
|
|
17
|
-
} & Exports;
|
|
18
|
-
(internal: unknown, props: {
|
|
19
|
-
$$events?: Events;
|
|
20
|
-
$$slots?: Slots;
|
|
21
|
-
}): Exports & {
|
|
22
|
-
$set?: any;
|
|
23
|
-
$on?: any;
|
|
24
|
-
};
|
|
25
|
-
z_$$bindings?: Bindings;
|
|
26
|
-
}
|
|
8
|
+
declare const Tooltips: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
9
|
+
type Tooltips = ReturnType<typeof Tooltips>;
|
|
10
|
+
export default Tooltips;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.tooltip-trigger {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
cursor: help;
|
|
6
|
+
outline: none;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.tooltip-content {
|
|
10
|
+
background-color: var(--content-primary);
|
|
11
|
+
color: var(--content-inversed);
|
|
12
|
+
padding: 12px 12px;
|
|
13
|
+
border-radius: 12px;
|
|
14
|
+
font-size: 14px;
|
|
15
|
+
font-weight: 500;
|
|
16
|
+
max-width: 200px;
|
|
17
|
+
word-wrap: break-word;
|
|
18
|
+
/* box-shadow: 0 0 12px rgba(0, 0, 0, 0.12); */
|
|
19
|
+
animation: tooltip-in 200ms ease-out;
|
|
20
|
+
z-index: 1000;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@keyframes tooltip-in {
|
|
24
|
+
from {
|
|
25
|
+
opacity: 0;
|
|
26
|
+
transform: scale(0.95);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
to {
|
|
30
|
+
opacity: 1;
|
|
31
|
+
transform: scale(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.tooltip-provider {
|
|
36
|
+
position: relative;
|
|
37
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import "./oka-style.css";
|
|
3
|
+
import { Tooltip } from "bits-ui";
|
|
3
4
|
let { children, ...props } = $props();
|
|
4
5
|
</script>
|
|
5
6
|
|
|
6
7
|
<div id="oka-style-container" {...props}>
|
|
7
|
-
|
|
8
|
+
<Tooltip.Provider>
|
|
9
|
+
{@render children()}
|
|
10
|
+
</Tooltip.Provider>
|
|
8
11
|
</div>
|
package/dist/index.d.ts
CHANGED
|
@@ -6,10 +6,12 @@ export { default as Dialog } from './components/core/dialog/Dialog.svelte';
|
|
|
6
6
|
export { default as Input } from './components/core/input/Input.svelte';
|
|
7
7
|
export { default as Loading } from './components/core/loading/Loading.svelte';
|
|
8
8
|
export { default as Pagination } from './components/core/pagination/Pagination.svelte';
|
|
9
|
+
export { default as PinInput } from './components/core/pin-input/PinInput.svelte';
|
|
9
10
|
export { default as SingleSelect } from './components/core/select/SingleSelect.svelte';
|
|
10
11
|
export { default as MultiSelect } from './components/core/select/MultiSelect.svelte';
|
|
11
12
|
export { default as Separator } from './components/core/separator/Separator.svelte';
|
|
12
13
|
export { default as Sidebar } from './components/core/sidebar/Sidebar.svelte';
|
|
14
|
+
export { default as Tooltips } from './components/core/tooltips/Tooltips.svelte';
|
|
13
15
|
export { default as OKAStyleProvider } from './components/styling/oka-style-provider/OKAStyleProvider.svelte';
|
|
14
16
|
export { default as ThemeSwitcher } from './components/styling/theme-switcher/ThemeSwitcher.svelte';
|
|
15
17
|
export { default as SVG31 } from './components/illustrations/SVG31.svelte';
|
package/dist/index.js
CHANGED
|
@@ -7,10 +7,12 @@ export { default as Dialog } from './components/core/dialog/Dialog.svelte';
|
|
|
7
7
|
export { default as Input } from './components/core/input/Input.svelte';
|
|
8
8
|
export { default as Loading } from './components/core/loading/Loading.svelte';
|
|
9
9
|
export { default as Pagination } from './components/core/pagination/Pagination.svelte';
|
|
10
|
+
export { default as PinInput } from './components/core/pin-input/PinInput.svelte';
|
|
10
11
|
export { default as SingleSelect } from './components/core/select/SingleSelect.svelte';
|
|
11
12
|
export { default as MultiSelect } from './components/core/select/MultiSelect.svelte';
|
|
12
13
|
export { default as Separator } from './components/core/separator/Separator.svelte';
|
|
13
14
|
export { default as Sidebar } from './components/core/sidebar/Sidebar.svelte';
|
|
15
|
+
export { default as Tooltips } from './components/core/tooltips/Tooltips.svelte';
|
|
14
16
|
// Styling & theming
|
|
15
17
|
export { default as OKAStyleProvider } from './components/styling/oka-style-provider/OKAStyleProvider.svelte';
|
|
16
18
|
export { default as ThemeSwitcher } from './components/styling/theme-switcher/ThemeSwitcher.svelte';
|