@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 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 {...contentProps} class="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: fit-content;
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 = $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
- declare const Input: import("svelte").Component<Props, {}, "ref" | "value">;
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;
@@ -24,7 +24,6 @@
24
24
  }
25
25
 
26
26
  .input:hover {
27
- background-color: var(--surface-secondary);
28
27
  border-color: var(--stroke-medium);
29
28
  }
30
29
 
@@ -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,5 @@
1
+ import "./pin-input.css";
2
+ import { PinInput } from "bits-ui";
3
+ declare const PinInput: import("svelte").Component<Omit<PinInput.RootProps, "children">, {}, "ref" | "value">;
4
+ type PinInput = ReturnType<typeof PinInput>;
5
+ export default PinInput;
@@ -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
- export default Tooltips;
2
- type Tooltips = SvelteComponent<{
3
- [x: string]: never;
4
- }, {
5
- [evt: string]: CustomEvent<any>;
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: $$__sveltets_2_IsomorphicComponent<{
10
- [x: string]: never;
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
- {@render children()}
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okaapp/oka-ui-sv",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "OKA UI Svelte components library for the Appta software platform",
5
5
  "license": "MIT",
6
6
  "scripts": {