@ttdk-design-system/library-react 0.0.0-stage → 1.0.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.
Files changed (184) hide show
  1. package/AI_GUIDE.md +6518 -0
  2. package/llms.txt +6518 -0
  3. package/package.json +1098 -4
  4. package/src/core/index.ts +2 -0
  5. package/src/core/tailwind-preset.cjs +62 -0
  6. package/src/core/tailwind-preset.ts +85 -0
  7. package/src/core/theme/tokens.css +663 -0
  8. package/src/core/types.ts +836 -0
  9. package/src/index.ts +17 -0
  10. package/src/tailwind-preset.cjs +62 -0
  11. package/src/tailwind-preset.ts +85 -0
  12. package/src/types.ts +1 -0
  13. package/src/web/accordion/AI_GUIDE.md +149 -0
  14. package/src/web/accordion/accordion.css +1 -0
  15. package/src/web/accordion/accordion.tsx +430 -0
  16. package/src/web/accordion/index.ts +3 -0
  17. package/src/web/accordion/manifest.json +351 -0
  18. package/src/web/alert/AI_GUIDE.md +139 -0
  19. package/src/web/alert/alert.css +1 -0
  20. package/src/web/alert/alert.tsx +318 -0
  21. package/src/web/alert/index.ts +3 -0
  22. package/src/web/alert/manifest.json +240 -0
  23. package/src/web/avatar/AI_GUIDE.md +118 -0
  24. package/src/web/avatar/avatar.css +1 -0
  25. package/src/web/avatar/avatar.tsx +233 -0
  26. package/src/web/avatar/index.ts +3 -0
  27. package/src/web/avatar/manifest.json +195 -0
  28. package/src/web/badge/AI_GUIDE.md +94 -0
  29. package/src/web/badge/badge.css +1 -0
  30. package/src/web/badge/badge.tsx +140 -0
  31. package/src/web/badge/index.ts +2 -0
  32. package/src/web/badge/manifest.json +141 -0
  33. package/src/web/banner/AI_GUIDE.md +130 -0
  34. package/src/web/banner/banner.css +1 -0
  35. package/src/web/banner/banner.tsx +334 -0
  36. package/src/web/banner/index.ts +3 -0
  37. package/src/web/banner/manifest.json +240 -0
  38. package/src/web/breadcrumb/AI_GUIDE.md +120 -0
  39. package/src/web/breadcrumb/breadcrumb.css +1 -0
  40. package/src/web/breadcrumb/breadcrumb.tsx +306 -0
  41. package/src/web/breadcrumb/index.ts +3 -0
  42. package/src/web/breadcrumb/manifest.json +225 -0
  43. package/src/web/button/AI_GUIDE.md +121 -0
  44. package/src/web/button/button.css +1 -0
  45. package/src/web/button/button.tsx +287 -0
  46. package/src/web/button/index.ts +2 -0
  47. package/src/web/button/manifest.json +177 -0
  48. package/src/web/calendar/AI_GUIDE.md +151 -0
  49. package/src/web/calendar/calendar.css +1 -0
  50. package/src/web/calendar/calendar.tsx +1611 -0
  51. package/src/web/calendar/index.ts +3 -0
  52. package/src/web/calendar/manifest.json +470 -0
  53. package/src/web/card/AI_GUIDE.md +133 -0
  54. package/src/web/card/card.css +1 -0
  55. package/src/web/card/card.tsx +408 -0
  56. package/src/web/card/index.ts +4 -0
  57. package/src/web/card/manifest.json +357 -0
  58. package/src/web/checkbox/AI_GUIDE.md +146 -0
  59. package/src/web/checkbox/checkbox.css +1 -0
  60. package/src/web/checkbox/checkbox.tsx +307 -0
  61. package/src/web/checkbox/index.ts +2 -0
  62. package/src/web/checkbox/manifest.json +294 -0
  63. package/src/web/chip/AI_GUIDE.md +186 -0
  64. package/src/web/chip/chip.css +1 -0
  65. package/src/web/chip/chip.tsx +230 -0
  66. package/src/web/chip/index.ts +2 -0
  67. package/src/web/chip/manifest.json +186 -0
  68. package/src/web/dropdown/AI_GUIDE.md +167 -0
  69. package/src/web/dropdown/dropdown.css +1 -0
  70. package/src/web/dropdown/dropdown.tsx +1274 -0
  71. package/src/web/dropdown/index.ts +3 -0
  72. package/src/web/dropdown/manifest.json +576 -0
  73. package/src/web/flex/AI_GUIDE.md +113 -0
  74. package/src/web/flex/flex-item.tsx +97 -0
  75. package/src/web/flex/flex.css +1 -0
  76. package/src/web/flex/flex.tsx +108 -0
  77. package/src/web/flex/index.ts +5 -0
  78. package/src/web/flex/manifest.json +162 -0
  79. package/src/web/form/index.ts +7 -0
  80. package/src/web/grid/AI_GUIDE.md +112 -0
  81. package/src/web/grid/grid-item.tsx +112 -0
  82. package/src/web/grid/grid.css +1 -0
  83. package/src/web/grid/grid.tsx +99 -0
  84. package/src/web/grid/index.ts +5 -0
  85. package/src/web/grid/manifest.json +153 -0
  86. package/src/web/index.ts +86 -0
  87. package/src/web/input/AI_GUIDE.md +159 -0
  88. package/src/web/input/index.ts +3 -0
  89. package/src/web/input/input.css +1 -0
  90. package/src/web/input/input.tsx +537 -0
  91. package/src/web/input/manifest.json +465 -0
  92. package/src/web/input-number/AI_GUIDE.md +164 -0
  93. package/src/web/input-number/index.ts +3 -0
  94. package/src/web/input-number/input-number.css +1 -0
  95. package/src/web/input-number/input-number.tsx +1193 -0
  96. package/src/web/input-number/manifest.json +575 -0
  97. package/src/web/modal/AI_GUIDE.md +171 -0
  98. package/src/web/modal/index.ts +3 -0
  99. package/src/web/modal/manifest.json +375 -0
  100. package/src/web/modal/modal.css +1 -0
  101. package/src/web/modal/modal.tsx +571 -0
  102. package/src/web/pagination/AI_GUIDE.md +148 -0
  103. package/src/web/pagination/index.ts +21 -0
  104. package/src/web/pagination/manifest.json +432 -0
  105. package/src/web/pagination/pagination-content.tsx +45 -0
  106. package/src/web/pagination/pagination-ellipsis.tsx +54 -0
  107. package/src/web/pagination/pagination-first.tsx +155 -0
  108. package/src/web/pagination/pagination-item.tsx +45 -0
  109. package/src/web/pagination/pagination-last.tsx +155 -0
  110. package/src/web/pagination/pagination-link.tsx +121 -0
  111. package/src/web/pagination/pagination-next.tsx +158 -0
  112. package/src/web/pagination/pagination-previous.tsx +158 -0
  113. package/src/web/pagination/pagination.css +1 -0
  114. package/src/web/pagination/pagination.tsx +687 -0
  115. package/src/web/popover/AI_GUIDE.md +163 -0
  116. package/src/web/popover/index.ts +3 -0
  117. package/src/web/popover/manifest.json +396 -0
  118. package/src/web/popover/popover.css +1 -0
  119. package/src/web/popover/popover.tsx +702 -0
  120. package/src/web/radio/AI_GUIDE.md +155 -0
  121. package/src/web/radio/index.ts +2 -0
  122. package/src/web/radio/manifest.json +294 -0
  123. package/src/web/radio/radio.css +1 -0
  124. package/src/web/radio/radio.tsx +290 -0
  125. package/src/web/selectbox/AI_GUIDE.md +216 -0
  126. package/src/web/selectbox/index.ts +3 -0
  127. package/src/web/selectbox/manifest.json +477 -0
  128. package/src/web/selectbox/selectbox.css +1 -0
  129. package/src/web/selectbox/selectbox.tsx +1048 -0
  130. package/src/web/sonner/AI_GUIDE.md +98 -0
  131. package/src/web/sonner/index.ts +114 -0
  132. package/src/web/sonner/manifest.json +132 -0
  133. package/src/web/sonner/sonner.css +1 -0
  134. package/src/web/sonner/sonner.tsx +177 -0
  135. package/src/web/table/AI_GUIDE.md +145 -0
  136. package/src/web/table/index.ts +35 -0
  137. package/src/web/table/manifest.json +168 -0
  138. package/src/web/table/table-body.tsx +45 -0
  139. package/src/web/table/table-caption.tsx +45 -0
  140. package/src/web/table/table-cell.tsx +74 -0
  141. package/src/web/table/table-empty.tsx +108 -0
  142. package/src/web/table/table-footer.tsx +45 -0
  143. package/src/web/table/table-head.tsx +80 -0
  144. package/src/web/table/table-header.tsx +45 -0
  145. package/src/web/table/table-row.tsx +69 -0
  146. package/src/web/table/table.css +1 -0
  147. package/src/web/table/table.tsx +305 -0
  148. package/src/web/tabs/AI_GUIDE.md +150 -0
  149. package/src/web/tabs/index.ts +3 -0
  150. package/src/web/tabs/manifest.json +315 -0
  151. package/src/web/tabs/tabs.css +1 -0
  152. package/src/web/tabs/tabs.tsx +332 -0
  153. package/src/web/text/AI_GUIDE.md +129 -0
  154. package/src/web/text/index.ts +3 -0
  155. package/src/web/text/manifest.json +195 -0
  156. package/src/web/text/text.css +1 -0
  157. package/src/web/text/text.tsx +689 -0
  158. package/src/web/textarea/AI_GUIDE.md +141 -0
  159. package/src/web/textarea/index.ts +3 -0
  160. package/src/web/textarea/manifest.json +438 -0
  161. package/src/web/textarea/textarea.css +1 -0
  162. package/src/web/textarea/textarea.tsx +467 -0
  163. package/src/web/tooltip/AI_GUIDE.md +110 -0
  164. package/src/web/tooltip/index.ts +3 -0
  165. package/src/web/tooltip/manifest.json +222 -0
  166. package/src/web/tooltip/tooltip.css +1 -0
  167. package/src/web/tooltip/tooltip.tsx +423 -0
  168. package/src/webview/bottomsheet/AI_GUIDE.md +141 -0
  169. package/src/webview/bottomsheet/bottomsheet.css +1 -0
  170. package/src/webview/bottomsheet/bottomsheet.tsx +603 -0
  171. package/src/webview/bottomsheet/index.ts +4 -0
  172. package/src/webview/bottomsheet/manifest.json +377 -0
  173. package/src/webview/button/AI_GUIDE.md +79 -0
  174. package/src/webview/button/button-ios.css +1 -0
  175. package/src/webview/button/button-ios.tsx +138 -0
  176. package/src/webview/button/button-material.css +1 -0
  177. package/src/webview/button/button-material.tsx +138 -0
  178. package/src/webview/button/index.ts +7 -0
  179. package/src/webview/button/manifest.json +148 -0
  180. package/src/webview/index.ts +7 -0
  181. package/tailwind-preset.cjs +62 -0
  182. package/tailwind-preset.js +62 -0
  183. package/ttdk-manifest.json +10188 -0
  184. package/README.md +0 -3
@@ -0,0 +1,98 @@
1
+ # <Sonner /> — TTDK Component Reference
2
+
3
+ Komponen Sonner / Toaster untuk sistem notifikasi toast mengambang yang ringkas, kaya warna, dan responsif.
4
+
5
+ ## 1. Stylesheets & Theming (Pure CSS)
6
+ Import the corresponding stylesheet for the theme you wish to use:
7
+ - **COMMON Theme**: `import "@ttdk-design-system/library-<react|vue|svelte>/web/sonner/sonner.css";`
8
+
9
+ ## 2. Subpath Component Import
10
+ ```ts
11
+ // React
12
+ import Sonner from "@ttdk-design-system/library-react/web/sonner";
13
+
14
+ // Vue 3
15
+ import Sonner from "@ttdk-design-system/library-vue/web/sonner";
16
+
17
+ // Svelte
18
+ import Sonner from "@ttdk-design-system/library-svelte/web/sonner";
19
+ ```
20
+
21
+ ## 3. Props & API Reference
22
+
23
+ | Prop | Type | Default | Description |
24
+ | :--- | :--- | :--- | :--- |
25
+ | `position?` | `'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'` | `bottom-right` | Posisi penempatan toast pada layar. - `'top-left'`, `'top-center'`, `'top-right'` - `'bottom-left'`, `'bottom-center'`, `'bottom-right'` |
26
+ | `richColors?` | `boolean` | `true` | Menampilkan warna semantik kaya (*rich colors*) untuk jenis status (sukses hijau, error merah, info biru, warning kuning). |
27
+ | `closeButton?` | `boolean` | `true` | Menampilkan tombol silang penutup (*close button*) pada setiap kartu toast. |
28
+ | `theme?` | `'light' | 'dark' | 'system'` | `light` | Menentukan tema visual kontainer toast (`'light'`, `'dark'`, atau `'system'`). |
29
+ | `expand?` | `boolean` | `false` | Membuka semua tumpukan toast secara melebar (*expanded*) secara default saat muncul. |
30
+ | `duration?` | `number` | `4000` | Durasi tampilan toast dalam milidetik sebelum otomatis menghilang. |
31
+ | `visibleToasts?` | `number` | `3` | Jumlah maksimum kartu toast yang terlihat bertumpuk secara bersamaan di layar. |
32
+ | `gap?` | `number` | `14` | Jarak vertikal antar kartu toast dalam piksel. |
33
+ | `offset?` | `number` | `24` | Jarak offset tepi layar dalam piksel. |
34
+ | `mobileOffset?` | `number` | `16` | Jarak offset pada perangkat seluler / mobile dalam piksel. |
35
+ | `dir?` | `'ltr' | 'rtl'` | `ltr` | Arah teks layout tata letak (`'ltr'` atau `'rtl'`). |
36
+ | `className?` | `string` | `-` | Kelas CSS kustom tambahan untuk wadah toaster. |
37
+
38
+ ## 4. Usage Examples
39
+
40
+ ### React Example
41
+ ```tsx
42
+ import Sonner from "@ttdk-design-system/library-react/web/sonner";
43
+ import "@ttdk-design-system/library-react/web/sonner/sonner.css";
44
+ import toast from "sonner-js";
45
+
46
+ export function Example() {
47
+ return (
48
+ <div>
49
+ <Sonner position="bottom-right" richColors />
50
+ <button onClick={() => toast.success("Data pasien berhasil disimpan!")}>
51
+ Tampilkan Toast Sukses
52
+ </button>
53
+ </div>
54
+ );
55
+ }
56
+ ```
57
+
58
+ ### Vue 3 Example
59
+ ```vue
60
+ <script setup lang="ts">
61
+ import Sonner from "@ttdk-design-system/library-vue/web/sonner";
62
+ import "@ttdk-design-system/library-vue/web/sonner/sonner.css";
63
+ import toast from "sonner-js";
64
+
65
+ const showToast = () => {
66
+ toast.success("Data pasien berhasil disimpan!");
67
+ };
68
+ </script>
69
+
70
+ <template>
71
+ <div>
72
+ <Sonner position="bottom-right" :rich-colors="true" />
73
+ <button @click="showToast">
74
+ Tampilkan Toast Sukses
75
+ </button>
76
+ </div>
77
+ </template>
78
+ ```
79
+
80
+ ### Svelte Example
81
+ ```svelte
82
+ <script lang="ts">
83
+ import Sonner from "@ttdk-design-system/library-svelte/web/sonner";
84
+ import "@ttdk-design-system/library-svelte/web/sonner/sonner.css";
85
+ import toast from "sonner-js";
86
+
87
+ const showToast = () => {
88
+ toast.success("Data pasien berhasil disimpan!");
89
+ };
90
+ </script>
91
+
92
+ <div>
93
+ <Sonner position="bottom-right" richColors={true} />
94
+ <button on:click={showToast}>
95
+ Tampilkan Toast Sukses
96
+ </button>
97
+ </div>
98
+ ```
@@ -0,0 +1,114 @@
1
+ import sonnerJsToast from 'sonner-js';
2
+ import SonnerComponent from './sonner';
3
+
4
+ export interface ToastAction {
5
+ label: string;
6
+ onClick: (event: MouseEvent) => void;
7
+ cancel?: boolean;
8
+ }
9
+
10
+ export interface ToastOptions {
11
+ position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
12
+ closeButton?: boolean;
13
+ richColors?: boolean;
14
+ duration?: number;
15
+ invert?: boolean;
16
+ description?: string;
17
+ action?: ToastAction;
18
+ onDismiss?: (toast?: any) => void;
19
+ onAutoClose?: (toast?: any) => void;
20
+ [key: string]: any;
21
+ }
22
+
23
+ export interface ToastPromiseOptions<T = any> {
24
+ loading?: string;
25
+ success?: string | ((data: T) => string);
26
+ error?: string | ((err: any) => string);
27
+ description?: string | ((data: any) => string);
28
+ finally?: () => void | Promise<void>;
29
+ }
30
+
31
+ export interface ToastInterface {
32
+ (message: string, options?: ToastOptions): string | number;
33
+ /**
34
+ * Compatibility property for Vue template unref / Volar __VLS_withDotValue closure.
35
+ */
36
+ readonly value: ToastInterface;
37
+ message: (message: string, options?: ToastOptions) => string | number;
38
+ success: (message: string, options?: ToastOptions) => string | number;
39
+ error: (message: string, options?: ToastOptions) => string | number;
40
+ danger: (message: string, options?: ToastOptions) => string | number;
41
+ info: (message: string, options?: ToastOptions) => string | number;
42
+ warning: (message: string, options?: ToastOptions) => string | number;
43
+ loading: (message: string, options?: ToastOptions) => string | number;
44
+ dismiss: (id?: number | string, exitTime?: number) => void;
45
+ promise: <T = any>(promise: Promise<T> | (() => Promise<T>), data?: ToastPromiseOptions<T>) => void;
46
+ config: (userConfig: any) => void;
47
+ }
48
+
49
+ function getRawToast(): any {
50
+ const t = sonnerJsToast as any;
51
+ if (t && typeof t.default === 'function') {
52
+ return t.default;
53
+ }
54
+ if (typeof t === 'function') {
55
+ return t;
56
+ }
57
+ return t?.default || t;
58
+ }
59
+
60
+ const toastFunction = (message: string, options?: ToastOptions) => {
61
+ const raw = getRawToast();
62
+ return typeof raw === 'function' ? raw(message, options) : undefined;
63
+ };
64
+
65
+ export const toast: ToastInterface = Object.assign(toastFunction, {
66
+ message: (message: string, options?: ToastOptions) => {
67
+ const raw = getRawToast();
68
+ return raw?.message ? raw.message(message, options) : raw?.(message, options);
69
+ },
70
+ success: (message: string, options?: ToastOptions) => getRawToast()?.success?.(message, options),
71
+ error: (message: string, options?: ToastOptions) => getRawToast()?.error?.(message, options),
72
+ danger: (message: string, options?: ToastOptions) => {
73
+ const raw = getRawToast();
74
+ return (raw?.danger || raw?.error)?.(message, options);
75
+ },
76
+ info: (message: string, options?: ToastOptions) => getRawToast()?.info?.(message, options),
77
+ warning: (message: string, options?: ToastOptions) => getRawToast()?.warning?.(message, options),
78
+ loading: (message: string, options?: ToastOptions) => getRawToast()?.loading?.(message, options),
79
+ dismiss: (id?: number | string, exitTime?: number) => getRawToast()?.dismiss?.(id, exitTime),
80
+ promise: <T = any>(promise: Promise<T> | (() => Promise<T>), data?: ToastPromiseOptions<T>) => getRawToast()?.promise?.(promise, data),
81
+ config: (userConfig: any) => getRawToast()?.config?.(userConfig),
82
+ }) as ToastInterface;
83
+
84
+ try {
85
+ Object.defineProperty(toast, 'value', {
86
+ get() {
87
+ return toast;
88
+ },
89
+ enumerable: true,
90
+ configurable: true,
91
+ });
92
+ } catch (_) {}
93
+
94
+ if (typeof window !== 'undefined') {
95
+ try {
96
+ const raw = getRawToast();
97
+ if (raw && typeof raw.config === 'function') {
98
+ raw.config({
99
+ toastOptions: {
100
+ position: 'bottom-right',
101
+ closeButton: true,
102
+ richColors: true,
103
+ duration: 4000,
104
+ },
105
+ });
106
+ }
107
+ } catch (e) {
108
+ // Abaikan jika dieksekusi di lingkungan SSR / non-DOM
109
+ }
110
+ }
111
+
112
+ export { SonnerComponent as Sonner, SonnerComponent as Toaster };
113
+ export default SonnerComponent;
114
+ export type { SonnerProps, SonnerPosition, SonnerTheme } from './sonner';
@@ -0,0 +1,132 @@
1
+ {
2
+ "name": "@ttdk-design-system/sonner",
3
+ "component": "Sonner",
4
+ "folder": "sonner",
5
+ "description": "Komponen Sonner / Toaster untuk sistem notifikasi toast mengambang yang ringkas, kaya warna, dan responsif.",
6
+ "stylesheets": [
7
+ {
8
+ "theme": "common",
9
+ "file": "sonner.css",
10
+ "importPath": "web/sonner/sonner.css"
11
+ }
12
+ ],
13
+ "props": {
14
+ "position": {
15
+ "name": "position",
16
+ "type": "'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'",
17
+ "optional": true,
18
+ "default": "bottom-right",
19
+ "description": "Posisi penempatan toast pada layar. - `'top-left'`, `'top-center'`, `'top-right'` - `'bottom-left'`, `'bottom-center'`, `'bottom-right'`",
20
+ "example": null,
21
+ "param": null
22
+ },
23
+ "richColors": {
24
+ "name": "richColors",
25
+ "type": "boolean",
26
+ "optional": true,
27
+ "default": "true",
28
+ "description": "Menampilkan warna semantik kaya (*rich colors*) untuk jenis status (sukses hijau, error merah, info biru, warning kuning).",
29
+ "example": null,
30
+ "param": null
31
+ },
32
+ "closeButton": {
33
+ "name": "closeButton",
34
+ "type": "boolean",
35
+ "optional": true,
36
+ "default": "true",
37
+ "description": "Menampilkan tombol silang penutup (*close button*) pada setiap kartu toast.",
38
+ "example": null,
39
+ "param": null
40
+ },
41
+ "theme": {
42
+ "name": "theme",
43
+ "type": "'light' | 'dark' | 'system'",
44
+ "optional": true,
45
+ "default": "light",
46
+ "description": "Menentukan tema visual kontainer toast (`'light'`, `'dark'`, atau `'system'`).",
47
+ "example": null,
48
+ "param": null
49
+ },
50
+ "expand": {
51
+ "name": "expand",
52
+ "type": "boolean",
53
+ "optional": true,
54
+ "default": "false",
55
+ "description": "Membuka semua tumpukan toast secara melebar (*expanded*) secara default saat muncul.",
56
+ "example": null,
57
+ "param": null
58
+ },
59
+ "duration": {
60
+ "name": "duration",
61
+ "type": "number",
62
+ "optional": true,
63
+ "default": "4000",
64
+ "description": "Durasi tampilan toast dalam milidetik sebelum otomatis menghilang.",
65
+ "example": null,
66
+ "param": null
67
+ },
68
+ "visibleToasts": {
69
+ "name": "visibleToasts",
70
+ "type": "number",
71
+ "optional": true,
72
+ "default": "3",
73
+ "description": "Jumlah maksimum kartu toast yang terlihat bertumpuk secara bersamaan di layar.",
74
+ "example": null,
75
+ "param": null
76
+ },
77
+ "gap": {
78
+ "name": "gap",
79
+ "type": "number",
80
+ "optional": true,
81
+ "default": "14",
82
+ "description": "Jarak vertikal antar kartu toast dalam piksel.",
83
+ "example": null,
84
+ "param": null
85
+ },
86
+ "offset": {
87
+ "name": "offset",
88
+ "type": "number",
89
+ "optional": true,
90
+ "default": "24",
91
+ "description": "Jarak offset tepi layar dalam piksel.",
92
+ "example": null,
93
+ "param": null
94
+ },
95
+ "mobileOffset": {
96
+ "name": "mobileOffset",
97
+ "type": "number",
98
+ "optional": true,
99
+ "default": "16",
100
+ "description": "Jarak offset pada perangkat seluler / mobile dalam piksel.",
101
+ "example": null,
102
+ "param": null
103
+ },
104
+ "dir": {
105
+ "name": "dir",
106
+ "type": "'ltr' | 'rtl'",
107
+ "optional": true,
108
+ "default": "ltr",
109
+ "description": "Arah teks layout tata letak (`'ltr'` atau `'rtl'`).",
110
+ "example": null,
111
+ "param": null
112
+ },
113
+ "className": {
114
+ "name": "className",
115
+ "type": "string",
116
+ "optional": true,
117
+ "default": null,
118
+ "description": "Kelas CSS kustom tambahan untuk wadah toaster.",
119
+ "example": null,
120
+ "param": null
121
+ }
122
+ },
123
+ "subInterfaces": {},
124
+ "supportedFrameworks": [
125
+ "react",
126
+ "vue",
127
+ "svelte"
128
+ ],
129
+ "themes": [
130
+ "tw"
131
+ ]
132
+ }
@@ -0,0 +1 @@
1
+ [data-sonner-toasters]{font-family:var(--ttdk-font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}[data-sonner-toaster]{--width:360px;--border-radius:10px;--gap:12px;--offset:24px;--mobile-offset:16px;z-index:999999}[data-sonner-toaster][data-sonner-theme=light],:root:not(.dark) [data-sonner-toaster]{--normal-bg:var(--ttdk-bg-card);--normal-border:var(--ttdk-stroke-subtle);--normal-text:var(--ttdk-text-icon-primary);--normal-text2:var(--ttdk-text-icon-secondary);--normal-cancel-bg:var(--ttdk-bg-secondary-disabled);--success-bg:var(--ttdk-bg-status-success-subtle);--success-border:var(--ttdk-stroke-status-success);--success-text:var(--ttdk-text-icon-status-success);--info-bg:var(--ttdk-bg-status-info-subtle);--info-border:var(--ttdk-stroke-status-info);--info-text:var(--ttdk-text-icon-status-info);--warning-bg:var(--ttdk-bg-status-warning-subtle);--warning-border:var(--ttdk-stroke-status-warning);--warning-text:var(--ttdk-text-icon-status-warning);--error-bg:var(--ttdk-bg-status-error-subtle);--error-border:var(--ttdk-stroke-status-error);--error-text:var(--ttdk-text-icon-status-error)}[data-sonner-toaster][data-sonner-theme=dark],.dark [data-sonner-toaster]{--normal-bg:var(--ttdk-bg-card);--normal-border:var(--ttdk-stroke-subtle);--normal-text:var(--ttdk-text-icon-primary);--normal-text2:var(--ttdk-text-icon-secondary);--normal-cancel-bg:var(--ttdk-bg-secondary-disabled);--success-bg:var(--ttdk-color-green-900);--success-border:var(--ttdk-color-green-700);--success-text:var(--ttdk-color-green-300);--info-bg:var(--ttdk-color-blue-900);--info-border:var(--ttdk-color-blue-700);--info-text:var(--ttdk-color-blue-300);--warning-bg:var(--ttdk-color-orange-900);--warning-border:var(--ttdk-color-orange-700);--warning-text:var(--ttdk-color-orange-300);--error-bg:var(--ttdk-color-red-900);--error-border:var(--ttdk-color-red-700);--error-text:var(--ttdk-color-red-300)}[data-sonner-toast]{border-radius:var(--border-radius);border:1px solid var(--normal-border);background-color:var(--normal-bg);color:var(--normal-text);box-shadow:var(--ttdk-shadow-lg);gap:10px;padding:14px 16px;font-size:13px;line-height:1.4;transition:transform .3s cubic-bezier(.16,1,.3,1),opacity .3s cubic-bezier(.16,1,.3,1),height .3s}.dark [data-sonner-toast]{box-shadow:var(--ttdk-shadow-lg)}[data-sonner-toast] [data-content]{flex-direction:column;gap:3px;display:flex}[data-sonner-toast] [data-title]{color:inherit;letter-spacing:-.01em;font-size:13px;font-weight:600}[data-sonner-toast] [data-description]{color:var(--normal-text2);font-size:12px;font-weight:400;line-height:1.4}[data-sonner-toast] [data-button]{background:var(--normal-text);height:28px;color:var(--normal-bg);cursor:pointer;border:none;border-radius:6px;justify-content:center;align-items:center;padding:0 10px;font-family:inherit;font-size:12px;font-weight:600;transition:opacity .15s,transform .1s;display:inline-flex}[data-sonner-toast] [data-button]:hover{opacity:.9}[data-sonner-toast] [data-button]:active{transform:scale(.97)}[data-sonner-toast] [data-button][data-cancel]{background:var(--normal-cancel-bg);color:var(--normal-text)}[data-sonner-toast] [data-close-button=true]{background:var(--normal-bg);border:1px solid var(--normal-border);width:20px;height:20px;color:var(--normal-text2);cursor:pointer;border-radius:50%;justify-content:center;align-items:center;transition:background-color .15s,color .15s;display:flex}[data-sonner-toast] [data-close-button=true]:hover{background:var(--normal-cancel-bg);color:var(--normal-text)}[data-sonner-toast][data-rich-colors][data-type=success]{background:var(--success-bg);border-color:var(--success-border);color:var(--success-text)}[data-sonner-toast][data-rich-colors][data-type=info]{background:var(--info-bg);border-color:var(--info-border);color:var(--info-text)}[data-sonner-toast][data-rich-colors][data-type=warning]{background:var(--warning-bg);border-color:var(--warning-border);color:var(--warning-text)}[data-sonner-toast][data-rich-colors][data-type=error]{background:var(--error-bg);border-color:var(--error-border);color:var(--error-text)}
@@ -0,0 +1,177 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ import { useEffect } from "react";
4
+
5
+ export type SonnerPosition =
6
+ | "top-left"
7
+ | "top-center"
8
+ | "top-right"
9
+ | "bottom-left"
10
+ | "bottom-center"
11
+ | "bottom-right";
12
+ export type SonnerTheme = "light" | "dark" | "system";
13
+ export interface SonnerProps {
14
+ /**
15
+ * Inline CSS style kustom.
16
+ */
17
+ style?: React.CSSProperties;
18
+ /**
19
+ * Posisi penempatan toast pada layar.
20
+ * - `'top-left'`, `'top-center'`, `'top-right'`
21
+ * - `'bottom-left'`, `'bottom-center'`, `'bottom-right'`
22
+ *
23
+ * @default 'bottom-right'
24
+ */
25
+ position?:
26
+ | "top-left"
27
+ | "top-center"
28
+ | "top-right"
29
+ | "bottom-left"
30
+ | "bottom-center"
31
+ | "bottom-right";
32
+
33
+ /**
34
+ * Menampilkan warna semantik kaya (*rich colors*) untuk jenis status (sukses hijau, error merah, info biru, warning kuning).
35
+ *
36
+ * @default true
37
+ */
38
+ richColors?: boolean;
39
+
40
+ /**
41
+ * Menampilkan tombol silang penutup (*close button*) pada setiap kartu toast.
42
+ *
43
+ * @default true
44
+ */
45
+ closeButton?: boolean;
46
+
47
+ /**
48
+ * Menentukan tema visual kontainer toast (`'light'`, `'dark'`, atau `'system'`).
49
+ *
50
+ * @default 'light'
51
+ */
52
+ theme?: "light" | "dark" | "system";
53
+
54
+ /**
55
+ * Membuka semua tumpukan toast secara melebar (*expanded*) secara default saat muncul.
56
+ *
57
+ * @default false
58
+ */
59
+ expand?: boolean;
60
+
61
+ /**
62
+ * Durasi tampilan toast dalam milidetik sebelum otomatis menghilang.
63
+ *
64
+ * @default 4000
65
+ */
66
+ duration?: number;
67
+
68
+ /**
69
+ * Jumlah maksimum kartu toast yang terlihat bertumpuk secara bersamaan di layar.
70
+ *
71
+ * @default 3
72
+ */
73
+ visibleToasts?: number;
74
+
75
+ /**
76
+ * Jarak vertikal antar kartu toast dalam piksel.
77
+ *
78
+ * @default 14
79
+ */
80
+ gap?: number;
81
+
82
+ /**
83
+ * Jarak offset tepi layar dalam piksel.
84
+ *
85
+ * @default 24
86
+ */
87
+ offset?: number;
88
+
89
+ /**
90
+ * Jarak offset pada perangkat seluler / mobile dalam piksel.
91
+ *
92
+ * @default 16
93
+ */
94
+ mobileOffset?: number;
95
+
96
+ /**
97
+ * Arah teks layout tata letak (`'ltr'` atau `'rtl'`).
98
+ *
99
+ * @default 'ltr'
100
+ */
101
+ dir?: "ltr" | "rtl";
102
+
103
+ /**
104
+ * Kelas CSS kustom tambahan untuk wadah toaster.
105
+ */
106
+ className?: string;
107
+ }
108
+
109
+ /**
110
+ * Komponen Sonner / Toaster untuk sistem notifikasi toast mengambang yang ringkas, kaya warna, dan responsif.
111
+ */
112
+
113
+ import toast from "sonner-js";
114
+
115
+ function Sonner(props: SonnerProps) {
116
+ useEffect(() => {
117
+ toast.config({
118
+ theme: props.theme === "dark" ? "dark" : "light",
119
+ expand: props.expand ?? false,
120
+ visibleToasts: props.visibleToasts ?? 3,
121
+ gap: props.gap ?? 14,
122
+ offset: props.offset ?? 24,
123
+ mobileOffset: props.mobileOffset ?? 16,
124
+ dir: props.dir ?? "ltr",
125
+ toastOptions: {
126
+ position: props.position ?? "bottom-right",
127
+ closeButton: props.closeButton ?? true,
128
+ richColors: props.richColors ?? true,
129
+ duration: props.duration ?? 4000,
130
+ },
131
+ });
132
+ }, []);
133
+ useEffect(() => {
134
+ toast.config({
135
+ theme: props.theme === "dark" ? "dark" : "light",
136
+ expand: props.expand ?? false,
137
+ visibleToasts: props.visibleToasts ?? 3,
138
+ gap: props.gap ?? 14,
139
+ offset: props.offset ?? 24,
140
+ mobileOffset: props.mobileOffset ?? 16,
141
+ dir: props.dir ?? "ltr",
142
+ toastOptions: {
143
+ position: props.position ?? "bottom-right",
144
+ closeButton: props.closeButton ?? true,
145
+ richColors: props.richColors ?? true,
146
+ duration: props.duration ?? 4000,
147
+ },
148
+ });
149
+ }, [
150
+ props.position,
151
+ props.richColors,
152
+ props.closeButton,
153
+ props.theme,
154
+ props.expand,
155
+ props.duration,
156
+ props.visibleToasts,
157
+ props.gap,
158
+ props.offset,
159
+ props.mobileOffset,
160
+ props.dir,
161
+ ]);
162
+
163
+ return (
164
+ <div
165
+ aria-hidden="true"
166
+ className={`ttdk-sonner-wrapper ${props.className || ""}`}
167
+ style={{
168
+ display: "none",
169
+ ...props.style,
170
+ }}
171
+ />
172
+ );
173
+ }
174
+
175
+ export default Sonner;
176
+
177
+ export { Sonner };
@@ -0,0 +1,145 @@
1
+ # <Table /> — TTDK Component Reference
2
+
3
+ Komponen kontainer utama tabel (Compound Table ala Shadcn UI).
4
+
5
+ ## 1. Stylesheets & Theming (Pure CSS)
6
+ Import the corresponding stylesheet for the theme you wish to use:
7
+ - **COMMON Theme**: `import "@ttdk-design-system/library-<react|vue|svelte>/web/table/table.css";`
8
+
9
+ ## 2. Subpath Component Import
10
+ ```ts
11
+ // React
12
+ import Table from "@ttdk-design-system/library-react/web/table";
13
+
14
+ // Vue 3
15
+ import Table from "@ttdk-design-system/library-vue/web/table";
16
+
17
+ // Svelte
18
+ import Table from "@ttdk-design-system/library-svelte/web/table";
19
+ ```
20
+
21
+ ## 3. Props & API Reference
22
+
23
+ | Prop | Type | Default | Description |
24
+ | :--- | :--- | :--- | :--- |
25
+ | `variant?` | `'default' | 'striped' | 'clean'` | `default` | Varian tampilan visual tabel. - `'default'`: Tampilan standar dengan latar bersih dan bingkai kartu. - `'striped'`: Tampilan selang-seling (zebra). - `'clean'`: Tampilan minimalis tanpa border luar dan tanpa shadow. |
26
+ | `size?` | `'sm' | 'md' | 'lg'` | `md` | Kerapatan / ukuran tinggi baris tabel. - `'sm'`: Kompak (padat). - `'md'`: Standar. - `'lg'`: Lega. |
27
+ | `rounded?` | `'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | (string & {}) | number` | `sm` | Sudut kelengkungan radius tabel. - Preset: `'none'` | `'xs'` | `'sm'` | `'md'` | `'lg'` | `'xl'` | `'full'` - Nilai custom: `'12px'`, `'1rem'`, atau angka `12` |
28
+ | `shadow?` | `'none' | 'sm' | 'md' | 'lg' | (string & {})` | `sm` | Bayangan elevasi kontainer tabel. - Preset: `'none'` | `'sm'` | `'md'` | `'lg'` - Nilai custom: CSS box-shadow string (contoh: `'0 4px 20px rgba(0,0,0,0.1)'`) |
29
+ | `minWidth?` | `string | number` | `-` | Lebar minimum elemen table di dalam wrapper untuk menjaga susunan kolom dan memicu horizontal scroll. Contoh: `700`, `'700px'`, `'max-content'` |
30
+ | `maxHeight?` | `string | number` | `-` | Ketinggian maksimum kontainer tabel untuk memicu scroll vertikal internal (sangat direkomendasikan saat stickyHeader aktif). Contoh: `280`, `'280px'`, `'50vh'` |
31
+ | `hoverable?` | `boolean` | `true` | Efek hover saat kursor melayang di atas baris tabel. |
32
+ | `stickyHeader?` | `boolean` | `false` | Membuat header tabel menempel di atas (sticky) saat konten di-scroll. |
33
+ | `loading?` | `boolean` | `false` | Menampilkan spinner loading overlay di atas tabel. |
34
+ | `caption?` | `string` | `-` | Teks caption aksesibilitas untuk tabel (dirender sebagai elemen `<caption>`). |
35
+ | `style?` | `any` | `-` | Inline CSS style object native. |
36
+ | `ui?` | `UiProps` | `-` | Kustomisasi visual granular root kontainer wrapper (.ttdk-table-wrapper) melalui UiProps. |
37
+ | `tableStyle?` | `UiProps` | `-` | Style kustom untuk elemen table (table.ttdk-table) melalui UiProps. |
38
+ | `tableClass?` | `string` | `-` | Class CSS kustom untuk elemen table (table.ttdk-table). |
39
+ | `className?` | `string` | `-` | Class CSS kustom untuk kontainer wrapper luar. |
40
+ | `children?` | `any` | `-` | Konten anak (TableHeader, TableBody, TableFooter, TableCaption). |
41
+
42
+ ## 4. Usage Examples
43
+
44
+ ### React Example
45
+ ```tsx
46
+ import Table from "@ttdk-design-system/library-react/table";
47
+ import "@ttdk-design-system/library-react/table/table.css";
48
+
49
+ export function Example() {
50
+ return (
51
+ <Table variant="striped" size="md">
52
+ <thead>
53
+ <tr>
54
+ <th>Kode Faskes</th>
55
+ <th>Nama Fasilitas</th>
56
+ <th>Jenis</th>
57
+ <th>Status</th>
58
+ </tr>
59
+ </thead>
60
+ <tbody>
61
+ <tr>
62
+ <td>P320101</td>
63
+ <td>Puskesmas Cibinong</td>
64
+ <td>Puskesmas</td>
65
+ <td>Aktif</td>
66
+ </tr>
67
+ <tr>
68
+ <td>RS320102</td>
69
+ <td>RSUD Ciawi</td>
70
+ <td>Rumah Sakit</td>
71
+ <td>Aktif</td>
72
+ </tr>
73
+ </tbody>
74
+ </Table>
75
+ );
76
+ }
77
+ ```
78
+
79
+ ### Vue 3 Example
80
+ ```vue
81
+ <script setup lang="ts">
82
+ import Table from "@ttdk-design-system/library-vue/table";
83
+ import "@ttdk-design-system/library-vue/table/table.css";
84
+ </script>
85
+
86
+ <template>
87
+ <Table variant="striped" size="md">
88
+ <thead>
89
+ <tr>
90
+ <th>Kode Faskes</th>
91
+ <th>Nama Fasilitas</th>
92
+ <th>Jenis</th>
93
+ <th>Status</th>
94
+ </tr>
95
+ </thead>
96
+ <tbody>
97
+ <tr>
98
+ <td>P320101</td>
99
+ <td>Puskesmas Cibinong</td>
100
+ <td>Puskesmas</td>
101
+ <td>Aktif</td>
102
+ </tr>
103
+ <tr>
104
+ <td>RS320102</td>
105
+ <td>RSUD Ciawi</td>
106
+ <td>Rumah Sakit</td>
107
+ <td>Aktif</td>
108
+ </tr>
109
+ </tbody>
110
+ </Table>
111
+ </template>
112
+ ```
113
+
114
+ ### Svelte Example
115
+ ```svelte
116
+ <script lang="ts">
117
+ import Table from "@ttdk-design-system/library-svelte/table";
118
+ import "@ttdk-design-system/library-svelte/table/table.css";
119
+ </script>
120
+
121
+ <Table variant="striped" size="md">
122
+ <thead>
123
+ <tr>
124
+ <th>Kode Faskes</th>
125
+ <th>Nama Fasilitas</th>
126
+ <th>Jenis</th>
127
+ <th>Status</th>
128
+ </tr>
129
+ </thead>
130
+ <tbody>
131
+ <tr>
132
+ <td>P320101</td>
133
+ <td>Puskesmas Cibinong</td>
134
+ <td>Puskesmas</td>
135
+ <td>Aktif</td>
136
+ </tr>
137
+ <tr>
138
+ <td>RS320102</td>
139
+ <td>RSUD Ciawi</td>
140
+ <td>Rumah Sakit</td>
141
+ <td>Aktif</td>
142
+ </tr>
143
+ </tbody>
144
+ </Table>
145
+ ```