@ttdk-design-system/library-react 0.0.0-stage → 1.0.1

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/README.md +106 -2
  3. package/llms.txt +6518 -0
  4. package/package.json +1099 -4
  5. package/src/core/index.ts +2 -0
  6. package/src/core/tailwind-preset.cjs +62 -0
  7. package/src/core/tailwind-preset.ts +85 -0
  8. package/src/core/theme/tokens.css +663 -0
  9. package/src/core/types.ts +836 -0
  10. package/src/index.ts +17 -0
  11. package/src/tailwind-preset.cjs +62 -0
  12. package/src/tailwind-preset.ts +85 -0
  13. package/src/types.ts +1 -0
  14. package/src/web/accordion/AI_GUIDE.md +149 -0
  15. package/src/web/accordion/accordion.css +1 -0
  16. package/src/web/accordion/accordion.tsx +430 -0
  17. package/src/web/accordion/index.ts +3 -0
  18. package/src/web/accordion/manifest.json +351 -0
  19. package/src/web/alert/AI_GUIDE.md +139 -0
  20. package/src/web/alert/alert.css +1 -0
  21. package/src/web/alert/alert.tsx +318 -0
  22. package/src/web/alert/index.ts +3 -0
  23. package/src/web/alert/manifest.json +240 -0
  24. package/src/web/avatar/AI_GUIDE.md +118 -0
  25. package/src/web/avatar/avatar.css +1 -0
  26. package/src/web/avatar/avatar.tsx +233 -0
  27. package/src/web/avatar/index.ts +3 -0
  28. package/src/web/avatar/manifest.json +195 -0
  29. package/src/web/badge/AI_GUIDE.md +94 -0
  30. package/src/web/badge/badge.css +1 -0
  31. package/src/web/badge/badge.tsx +140 -0
  32. package/src/web/badge/index.ts +2 -0
  33. package/src/web/badge/manifest.json +141 -0
  34. package/src/web/banner/AI_GUIDE.md +130 -0
  35. package/src/web/banner/banner.css +1 -0
  36. package/src/web/banner/banner.tsx +334 -0
  37. package/src/web/banner/index.ts +3 -0
  38. package/src/web/banner/manifest.json +240 -0
  39. package/src/web/breadcrumb/AI_GUIDE.md +120 -0
  40. package/src/web/breadcrumb/breadcrumb.css +1 -0
  41. package/src/web/breadcrumb/breadcrumb.tsx +306 -0
  42. package/src/web/breadcrumb/index.ts +3 -0
  43. package/src/web/breadcrumb/manifest.json +225 -0
  44. package/src/web/button/AI_GUIDE.md +121 -0
  45. package/src/web/button/button.css +1 -0
  46. package/src/web/button/button.tsx +287 -0
  47. package/src/web/button/index.ts +2 -0
  48. package/src/web/button/manifest.json +177 -0
  49. package/src/web/calendar/AI_GUIDE.md +151 -0
  50. package/src/web/calendar/calendar.css +1 -0
  51. package/src/web/calendar/calendar.tsx +1611 -0
  52. package/src/web/calendar/index.ts +3 -0
  53. package/src/web/calendar/manifest.json +470 -0
  54. package/src/web/card/AI_GUIDE.md +133 -0
  55. package/src/web/card/card.css +1 -0
  56. package/src/web/card/card.tsx +408 -0
  57. package/src/web/card/index.ts +4 -0
  58. package/src/web/card/manifest.json +357 -0
  59. package/src/web/checkbox/AI_GUIDE.md +146 -0
  60. package/src/web/checkbox/checkbox.css +1 -0
  61. package/src/web/checkbox/checkbox.tsx +307 -0
  62. package/src/web/checkbox/index.ts +2 -0
  63. package/src/web/checkbox/manifest.json +294 -0
  64. package/src/web/chip/AI_GUIDE.md +186 -0
  65. package/src/web/chip/chip.css +1 -0
  66. package/src/web/chip/chip.tsx +230 -0
  67. package/src/web/chip/index.ts +2 -0
  68. package/src/web/chip/manifest.json +186 -0
  69. package/src/web/dropdown/AI_GUIDE.md +167 -0
  70. package/src/web/dropdown/dropdown.css +1 -0
  71. package/src/web/dropdown/dropdown.tsx +1274 -0
  72. package/src/web/dropdown/index.ts +3 -0
  73. package/src/web/dropdown/manifest.json +576 -0
  74. package/src/web/flex/AI_GUIDE.md +113 -0
  75. package/src/web/flex/flex-item.tsx +97 -0
  76. package/src/web/flex/flex.css +1 -0
  77. package/src/web/flex/flex.tsx +108 -0
  78. package/src/web/flex/index.ts +5 -0
  79. package/src/web/flex/manifest.json +162 -0
  80. package/src/web/form/index.ts +7 -0
  81. package/src/web/grid/AI_GUIDE.md +112 -0
  82. package/src/web/grid/grid-item.tsx +112 -0
  83. package/src/web/grid/grid.css +1 -0
  84. package/src/web/grid/grid.tsx +99 -0
  85. package/src/web/grid/index.ts +5 -0
  86. package/src/web/grid/manifest.json +153 -0
  87. package/src/web/index.ts +86 -0
  88. package/src/web/input/AI_GUIDE.md +159 -0
  89. package/src/web/input/index.ts +3 -0
  90. package/src/web/input/input.css +1 -0
  91. package/src/web/input/input.tsx +537 -0
  92. package/src/web/input/manifest.json +465 -0
  93. package/src/web/input-number/AI_GUIDE.md +164 -0
  94. package/src/web/input-number/index.ts +3 -0
  95. package/src/web/input-number/input-number.css +1 -0
  96. package/src/web/input-number/input-number.tsx +1193 -0
  97. package/src/web/input-number/manifest.json +575 -0
  98. package/src/web/modal/AI_GUIDE.md +171 -0
  99. package/src/web/modal/index.ts +3 -0
  100. package/src/web/modal/manifest.json +375 -0
  101. package/src/web/modal/modal.css +1 -0
  102. package/src/web/modal/modal.tsx +571 -0
  103. package/src/web/pagination/AI_GUIDE.md +148 -0
  104. package/src/web/pagination/index.ts +21 -0
  105. package/src/web/pagination/manifest.json +432 -0
  106. package/src/web/pagination/pagination-content.tsx +45 -0
  107. package/src/web/pagination/pagination-ellipsis.tsx +54 -0
  108. package/src/web/pagination/pagination-first.tsx +155 -0
  109. package/src/web/pagination/pagination-item.tsx +45 -0
  110. package/src/web/pagination/pagination-last.tsx +155 -0
  111. package/src/web/pagination/pagination-link.tsx +121 -0
  112. package/src/web/pagination/pagination-next.tsx +158 -0
  113. package/src/web/pagination/pagination-previous.tsx +158 -0
  114. package/src/web/pagination/pagination.css +1 -0
  115. package/src/web/pagination/pagination.tsx +687 -0
  116. package/src/web/popover/AI_GUIDE.md +163 -0
  117. package/src/web/popover/index.ts +3 -0
  118. package/src/web/popover/manifest.json +396 -0
  119. package/src/web/popover/popover.css +1 -0
  120. package/src/web/popover/popover.tsx +702 -0
  121. package/src/web/radio/AI_GUIDE.md +155 -0
  122. package/src/web/radio/index.ts +2 -0
  123. package/src/web/radio/manifest.json +294 -0
  124. package/src/web/radio/radio.css +1 -0
  125. package/src/web/radio/radio.tsx +290 -0
  126. package/src/web/selectbox/AI_GUIDE.md +216 -0
  127. package/src/web/selectbox/index.ts +3 -0
  128. package/src/web/selectbox/manifest.json +477 -0
  129. package/src/web/selectbox/selectbox.css +1 -0
  130. package/src/web/selectbox/selectbox.tsx +1048 -0
  131. package/src/web/sonner/AI_GUIDE.md +98 -0
  132. package/src/web/sonner/index.ts +114 -0
  133. package/src/web/sonner/manifest.json +132 -0
  134. package/src/web/sonner/sonner.css +1 -0
  135. package/src/web/sonner/sonner.tsx +177 -0
  136. package/src/web/table/AI_GUIDE.md +145 -0
  137. package/src/web/table/index.ts +35 -0
  138. package/src/web/table/manifest.json +168 -0
  139. package/src/web/table/table-body.tsx +45 -0
  140. package/src/web/table/table-caption.tsx +45 -0
  141. package/src/web/table/table-cell.tsx +74 -0
  142. package/src/web/table/table-empty.tsx +108 -0
  143. package/src/web/table/table-footer.tsx +45 -0
  144. package/src/web/table/table-head.tsx +80 -0
  145. package/src/web/table/table-header.tsx +45 -0
  146. package/src/web/table/table-row.tsx +69 -0
  147. package/src/web/table/table.css +1 -0
  148. package/src/web/table/table.tsx +305 -0
  149. package/src/web/tabs/AI_GUIDE.md +150 -0
  150. package/src/web/tabs/index.ts +3 -0
  151. package/src/web/tabs/manifest.json +315 -0
  152. package/src/web/tabs/tabs.css +1 -0
  153. package/src/web/tabs/tabs.tsx +332 -0
  154. package/src/web/text/AI_GUIDE.md +129 -0
  155. package/src/web/text/index.ts +3 -0
  156. package/src/web/text/manifest.json +195 -0
  157. package/src/web/text/text.css +1 -0
  158. package/src/web/text/text.tsx +689 -0
  159. package/src/web/textarea/AI_GUIDE.md +141 -0
  160. package/src/web/textarea/index.ts +3 -0
  161. package/src/web/textarea/manifest.json +438 -0
  162. package/src/web/textarea/textarea.css +1 -0
  163. package/src/web/textarea/textarea.tsx +467 -0
  164. package/src/web/tooltip/AI_GUIDE.md +110 -0
  165. package/src/web/tooltip/index.ts +3 -0
  166. package/src/web/tooltip/manifest.json +222 -0
  167. package/src/web/tooltip/tooltip.css +1 -0
  168. package/src/web/tooltip/tooltip.tsx +423 -0
  169. package/src/webview/bottomsheet/AI_GUIDE.md +141 -0
  170. package/src/webview/bottomsheet/bottomsheet.css +1 -0
  171. package/src/webview/bottomsheet/bottomsheet.tsx +603 -0
  172. package/src/webview/bottomsheet/index.ts +4 -0
  173. package/src/webview/bottomsheet/manifest.json +377 -0
  174. package/src/webview/button/AI_GUIDE.md +79 -0
  175. package/src/webview/button/button-ios.css +1 -0
  176. package/src/webview/button/button-ios.tsx +138 -0
  177. package/src/webview/button/button-material.css +1 -0
  178. package/src/webview/button/button-material.tsx +138 -0
  179. package/src/webview/button/index.ts +7 -0
  180. package/src/webview/button/manifest.json +148 -0
  181. package/src/webview/index.ts +7 -0
  182. package/tailwind-preset.cjs +62 -0
  183. package/tailwind-preset.js +62 -0
  184. package/ttdk-manifest.json +10188 -0
@@ -0,0 +1 @@
1
+ .ttdk-button{box-sizing:border-box;font-family:var(--ttdk-font-sans);font-weight:var(--ttdk-ui-font-weight,600);font-size:var(--ttdk-ui-font-size,inherit);cursor:pointer;user-select:none;white-space:nowrap;vertical-align:middle;transition:var(--ttdk-ui-transition,background-color .15s ease, border-color .15s ease, color .15s ease, box-shadow .15s ease, transform .1s ease, opacity .1s ease);border-style:solid;border-width:var(--ttdk-ui-border-width,1px);border-color:var(--ttdk-ui-border-color,transparent);border-radius:var(--ttdk-ui-border-radius,initial);outline:var(--ttdk-ui-outline,none);padding:var(--ttdk-ui-padding,initial);height:var(--ttdk-ui-height,initial);min-height:var(--ttdk-ui-min-height,initial);width:var(--ttdk-ui-width,initial);min-width:var(--ttdk-ui-min-width,initial);box-shadow:var(--ttdk-ui-box-shadow,none);opacity:var(--ttdk-ui-opacity,1);filter:var(--ttdk-ui-filter,none);transform:var(--ttdk-ui-transform,none);justify-content:center;align-items:center;gap:8px;text-decoration:none;display:inline-flex;&:hover:not(:disabled)[style*=--ttdk-ui-hover-background]{background:var(--ttdk-ui-hover-background)!important}&:hover:not(:disabled)[style*=--ttdk-ui-hover-color]{color:var(--ttdk-ui-hover-color)!important}&:hover:not(:disabled)[style*=--ttdk-ui-hover-border-color]{border-color:var(--ttdk-ui-hover-border-color)!important}&:hover:not(:disabled)[style*=--ttdk-ui-hover-transform]{transform:var(--ttdk-ui-hover-transform)!important}&:hover:not(:disabled)[style*=--ttdk-ui-hover-opacity]{opacity:var(--ttdk-ui-hover-opacity)!important}&:hover:not(:disabled)[style*=--ttdk-ui-hover-box-shadow]{box-shadow:var(--ttdk-ui-hover-box-shadow)!important}&:active:not(:disabled)[style*=--ttdk-ui-active-background]{background:var(--ttdk-ui-active-background)!important}&:active:not(:disabled)[style*=--ttdk-ui-active-color]{color:var(--ttdk-ui-active-color)!important}&:active:not(:disabled)[style*=--ttdk-ui-active-transform]{transform:var(--ttdk-ui-active-transform)!important}&:active:not(:disabled)[style*=--ttdk-ui-active-opacity]{opacity:var(--ttdk-ui-active-opacity)!important}&:focus-visible[style*=--ttdk-ui-focus-outline]{outline:var(--ttdk-ui-focus-outline)!important}&:focus-visible[style*=--ttdk-ui-focus-box-shadow]{box-shadow:var(--ttdk-ui-focus-box-shadow)!important}& svg,& .ttdk-icon{color:var(--ttdk-ui-icon-color,currentColor);width:var(--ttdk-ui-icon-size,1em);height:var(--ttdk-ui-icon-size,1em)}&[data-appearance=solid][data-variant=primary],&[data-variant=primary]:not([data-appearance]){background-color:var(--ttdk-brand-default);color:var(--ttdk-color-white);border-color:var(--ttdk-brand-default);&:hover:not(:disabled){background-color:var(--ttdk-brand-strong);border-color:var(--ttdk-brand-strong);color:var(--ttdk-color-white)}}&[data-appearance=solid][data-variant=info],&[data-variant=info]:not([data-appearance]){background-color:var(--ttdk-bg-status-info);color:var(--ttdk-color-white);border-color:var(--ttdk-bg-status-info);&:hover:not(:disabled){background-color:var(--ttdk-bg-status-info-strong);border-color:var(--ttdk-bg-status-info-strong);color:var(--ttdk-color-white)}}&[data-appearance=solid][data-variant=warning],&[data-variant=warning]:not([data-appearance]){background-color:var(--ttdk-bg-status-warning);color:var(--ttdk-color-black);border-color:var(--ttdk-bg-status-warning);&:hover:not(:disabled){background-color:var(--ttdk-bg-status-warning-strong);border-color:var(--ttdk-bg-status-warning-strong);color:var(--ttdk-color-white)}}&[data-appearance=solid][data-variant=danger],&[data-variant=danger]:not([data-appearance]){background-color:var(--ttdk-bg-status-error);color:var(--ttdk-color-white);border-color:var(--ttdk-bg-status-error);&:hover:not(:disabled){background-color:var(--ttdk-bg-status-error-strong);border-color:var(--ttdk-bg-status-error-strong);color:var(--ttdk-color-white)}}&[data-appearance=solid][data-variant=neutral],&[data-variant=neutral]:not([data-appearance]){background-color:var(--ttdk-bg-secondary-disabled);border-color:var(--ttdk-stroke-divider);color:var(--ttdk-text-icon-primary);&:hover:not(:disabled){background-color:var(--ttdk-stroke-divider);border-color:var(--ttdk-stroke-strong);color:var(--ttdk-text-icon-primary)}}&[data-appearance=solid][data-variant=disabled],&[data-variant=disabled]:not([data-appearance]){background-color:var(--ttdk-bg-secondary-disabled)!important;border-color:var(--ttdk-stroke-subtle)!important;color:var(--ttdk-text-icon-disabled)!important;cursor:not-allowed!important}&[data-appearance=soft][data-variant=primary]{background-color:var(--ttdk-brand-subtle);border-color:var(--ttdk-brand-default);color:var(--ttdk-brand-default);&:hover:not(:disabled){background-color:var(--ttdk-color-brand-green-100);border-color:var(--ttdk-brand-strong);color:var(--ttdk-brand-strong)}}&[data-appearance=soft][data-variant=info]{background-color:var(--ttdk-bg-status-info-subtle);border-color:var(--ttdk-stroke-status-info);color:var(--ttdk-text-icon-status-info);&:hover:not(:disabled){border-color:var(--ttdk-text-icon-status-info-strong);color:var(--ttdk-text-icon-status-info-strong);background-color:#2196f333}}&[data-appearance=soft][data-variant=warning]{background-color:var(--ttdk-bg-status-warning-subtle);border-color:var(--ttdk-stroke-status-warning);color:var(--ttdk-text-icon-status-warning);&:hover:not(:disabled){border-color:var(--ttdk-text-icon-status-warning-strong);color:var(--ttdk-text-icon-status-warning-strong);background-color:#fb8c0033}}&[data-appearance=soft][data-variant=danger]{background-color:var(--ttdk-bg-status-error-subtle);border-color:var(--ttdk-stroke-status-error);color:var(--ttdk-text-icon-status-error);&:hover:not(:disabled){border-color:var(--ttdk-text-icon-status-error-strong);color:var(--ttdk-text-icon-status-error-strong);background-color:#d0021b33}}&[data-appearance=soft][data-variant=neutral]{background-color:var(--ttdk-bg-secondary-disabled);border-color:var(--ttdk-stroke-divider);color:var(--ttdk-text-icon-primary);&:hover:not(:disabled){background-color:var(--ttdk-stroke-divider);border-color:var(--ttdk-stroke-strong);color:var(--ttdk-text-icon-primary)}}&[data-appearance=soft][data-variant=disabled]{background-color:var(--ttdk-bg-secondary-disabled)!important;border-color:var(--ttdk-stroke-subtle)!important;color:var(--ttdk-text-icon-disabled)!important;cursor:not-allowed!important}&[data-appearance=outline][data-variant=primary]{border-color:var(--ttdk-brand-default);color:var(--ttdk-brand-default);background-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-brand-subtle);border-color:var(--ttdk-brand-strong);color:var(--ttdk-brand-strong)}}&[data-appearance=outline][data-variant=info]{border-color:var(--ttdk-stroke-status-info);color:var(--ttdk-text-icon-status-info);background-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-status-info-subtle);border-color:var(--ttdk-text-icon-status-info-strong);color:var(--ttdk-text-icon-status-info-strong)}}&[data-appearance=outline][data-variant=warning]{border-color:var(--ttdk-stroke-status-warning);color:var(--ttdk-text-icon-status-warning);background-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-status-warning-subtle);border-color:var(--ttdk-text-icon-status-warning-strong);color:var(--ttdk-text-icon-status-warning-strong)}}&[data-appearance=outline][data-variant=danger]{border-color:var(--ttdk-stroke-status-error);color:var(--ttdk-text-icon-status-error);background-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-status-error-subtle);border-color:var(--ttdk-text-icon-status-error-strong);color:var(--ttdk-text-icon-status-error-strong)}}&[data-appearance=outline][data-variant=neutral]{border-color:var(--ttdk-stroke-divider);color:var(--ttdk-text-icon-primary);background-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-secondary-disabled);border-color:var(--ttdk-stroke-strong);color:var(--ttdk-text-icon-primary)}}&[data-appearance=outline][data-variant=disabled]{border-color:var(--ttdk-stroke-subtle)!important;color:var(--ttdk-text-icon-disabled)!important;cursor:not-allowed!important;background-color:#0000!important}&[data-appearance=link][data-variant=primary]{color:var(--ttdk-brand-default);text-underline-offset:4px;background-color:#0000;border-color:#0000;text-decoration:none;&:hover:not(:disabled){color:var(--ttdk-brand-strong);background-color:#0000;text-decoration:underline}}&[data-appearance=link][data-variant=info]{color:var(--ttdk-text-icon-status-info);text-underline-offset:4px;background-color:#0000;border-color:#0000;text-decoration:none;&:hover:not(:disabled){color:var(--ttdk-text-icon-status-info-strong);background-color:#0000;text-decoration:underline}}&[data-appearance=link][data-variant=warning]{color:var(--ttdk-text-icon-status-warning);text-underline-offset:4px;background-color:#0000;border-color:#0000;text-decoration:none;&:hover:not(:disabled){color:var(--ttdk-text-icon-status-warning-strong);background-color:#0000;text-decoration:underline}}&[data-appearance=link][data-variant=danger]{color:var(--ttdk-text-icon-status-error);text-underline-offset:4px;background-color:#0000;border-color:#0000;text-decoration:none;&:hover:not(:disabled){color:var(--ttdk-text-icon-status-error-strong);background-color:#0000;text-decoration:underline}}&[data-appearance=link][data-variant=neutral]{color:var(--ttdk-text-icon-primary);text-underline-offset:4px;background-color:#0000;border-color:#0000;text-decoration:none;&:hover:not(:disabled){color:var(--ttdk-text-icon-secondary);background-color:#0000;text-decoration:underline}}&[data-appearance=link][data-variant=disabled]{color:var(--ttdk-text-icon-disabled)!important;cursor:not-allowed!important;background-color:#0000!important;border-color:#0000!important;text-decoration:none!important}&[data-appearance=ghost][data-variant=primary]{color:var(--ttdk-brand-default);background-color:#0000;border-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-brand-subtle);color:var(--ttdk-brand-strong);border-color:#0000}&:active:not(:disabled){background-color:var(--ttdk-color-brand-green-100);color:var(--ttdk-brand-strong);border-color:#0000}}&[data-appearance=ghost][data-variant=info]{color:var(--ttdk-text-icon-status-info);background-color:#0000;border-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-status-info-subtle);color:var(--ttdk-text-icon-status-info-strong);border-color:#0000}&:active:not(:disabled){color:var(--ttdk-text-icon-status-info-strong);background-color:#2196f333;border-color:#0000}}&[data-appearance=ghost][data-variant=warning]{color:var(--ttdk-text-icon-status-warning);background-color:#0000;border-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-status-warning-subtle);color:var(--ttdk-text-icon-status-warning-strong);border-color:#0000}&:active:not(:disabled){color:var(--ttdk-text-icon-status-warning-strong);background-color:#fb8c0033;border-color:#0000}}&[data-appearance=ghost][data-variant=danger]{color:var(--ttdk-text-icon-status-error);background-color:#0000;border-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-status-error-subtle);color:var(--ttdk-text-icon-status-error-strong);border-color:#0000}&:active:not(:disabled){color:var(--ttdk-text-icon-status-error-strong);background-color:#d0021b33;border-color:#0000}}&[data-appearance=ghost][data-variant=neutral]{color:var(--ttdk-text-icon-primary);background-color:#0000;border-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-bg-secondary-disabled);color:var(--ttdk-text-icon-primary);border-color:#0000}&:active:not(:disabled){background-color:var(--ttdk-stroke-divider);color:var(--ttdk-text-icon-primary);border-color:#0000}}&[data-appearance=ghost][data-variant=disabled]{color:var(--ttdk-text-icon-disabled)!important;cursor:not-allowed!important;background-color:#0000!important;border-color:#0000!important}&[data-size=small],&[data-size=sm]{border-radius:var(--ttdk-radius-xs,6px);gap:6px;height:36px;padding:0 12px;font-size:12px;line-height:16px;&>svg,&>span:not(.ttdk-button-spinner)>svg{width:16px;height:16px}& .ttdk-button-spinner,& .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,16px)!important;height:var(--ttdk-ui-icon-size,16px)!important}}&[data-size=medium],&[data-size=md]{border-radius:var(--ttdk-radius-sm,8px);gap:8px;height:48px;padding:0 16px;font-size:16px;line-height:24px;&>svg,&>span:not(.ttdk-button-spinner)>svg{width:20px;height:20px}& .ttdk-button-spinner,& .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,20px)!important;height:var(--ttdk-ui-icon-size,20px)!important}}&[data-size=large],&[data-size=lg]{border-radius:var(--ttdk-radius-sm,8px);gap:8px;height:56px;padding:0 20px;font-size:18px;line-height:26px;&>svg,&>span:not(.ttdk-button-spinner)>svg{width:24px;height:24px}& .ttdk-button-spinner,& .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,24px)!important;height:var(--ttdk-ui-icon-size,24px)!important}}&[data-size=xs]{border-radius:var(--ttdk-radius-xs,4px);gap:4px;height:28px;padding:0 8px;font-size:11px;line-height:16px;&>svg,&>span:not(.ttdk-button-spinner)>svg{width:14px;height:14px}& .ttdk-button-spinner,& .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,14px)!important;height:var(--ttdk-ui-icon-size,14px)!important}}&[data-size=xl]{border-radius:var(--ttdk-radius-sm,8px);gap:8px;height:48px;padding:0 16px;font-size:16px;line-height:24px;&>svg,&>span:not(.ttdk-button-spinner)>svg{width:20px;height:20px}& .ttdk-button-spinner,& .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,20px)!important;height:var(--ttdk-ui-icon-size,20px)!important}}&[data-size="2xl"]{border-radius:var(--ttdk-radius-sm,8px);gap:10px;height:56px;padding:0 24px;font-size:18px;line-height:26px;&>svg,&>span:not(.ttdk-button-spinner)>svg{width:24px;height:24px}& .ttdk-button-spinner,& .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,24px)!important;height:var(--ttdk-ui-icon-size,24px)!important}}&[data-icon-only=true]{aspect-ratio:1;justify-content:center;padding:0}&[data-block=true]{width:100%}&[data-underline=none],&[data-appearance=link][data-underline=none]{text-decoration:none!important;&:hover:not(:disabled){text-decoration:none!important}}&[data-underline=always]{text-decoration:underline!important}&>svg,&>span:not(.ttdk-button-spinner)>svg{pointer-events:none;flex-shrink:0}& .ttdk-button-spinner{width:var(--ttdk-ui-icon-size,20px);height:var(--ttdk-ui-icon-size,20px);flex-shrink:0;justify-content:center;align-items:center;line-height:1;animation:1.2s steps(12,end) infinite ttdk-button-spin;display:inline-flex}& .ttdk-button-spinner svg{fill:none;stroke:currentColor;stroke-width:2.2px;stroke-linecap:round;display:block;width:100%!important;height:100%!important}&[data-size=xs] .ttdk-button-spinner,&[data-size=xs] .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,14px)!important;height:var(--ttdk-ui-icon-size,14px)!important}&[data-size=small] .ttdk-button-spinner,&[data-size=sm] .ttdk-button-spinner,&[data-size=small] .ttdk-button-spinner svg,&[data-size=sm] .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,16px)!important;height:var(--ttdk-ui-icon-size,16px)!important}&[data-size=medium] .ttdk-button-spinner,&[data-size=md] .ttdk-button-spinner,&[data-size=medium] .ttdk-button-spinner svg,&[data-size=md] .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,20px)!important;height:var(--ttdk-ui-icon-size,20px)!important}&[data-size=large] .ttdk-button-spinner,&[data-size=lg] .ttdk-button-spinner,&[data-size=large] .ttdk-button-spinner svg,&[data-size=lg] .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,24px)!important;height:var(--ttdk-ui-icon-size,24px)!important}&[data-size=xl] .ttdk-button-spinner,&[data-size=xl] .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,20px)!important;height:var(--ttdk-ui-icon-size,20px)!important}&[data-size="2xl"] .ttdk-button-spinner,&[data-size="2xl"] .ttdk-button-spinner svg{width:var(--ttdk-ui-icon-size,24px)!important;height:var(--ttdk-ui-icon-size,24px)!important}&:active:not(:disabled){scale:.98}&:focus-visible{box-shadow:0 0 0 3px color-mix(in oklab, var(--ttdk-brand-default) 30%, transparent);outline:none}&[data-variant=danger]:focus-visible{box-shadow:0 0 0 3px color-mix(in oklab, var(--ttdk-bg-status-error) 30%, transparent)}&:disabled:not([data-loading=true]),&[disabled]:not([data-loading=true]),&[data-disabled=true]:not([data-loading=true]){pointer-events:none;background-color:var(--ttdk-bg-secondary-disabled)!important;color:var(--ttdk-text-icon-disabled)!important;cursor:not-allowed!important;box-shadow:none!important;border-color:#0000!important}&[data-loading=true]{pointer-events:none;cursor:wait!important}&[data-loading=true][data-icon-only=true]>:not(.ttdk-button-spinner){display:none}}.ttdk-button[data-rounded=none]{border-radius:0}.ttdk-button[data-rounded=sm]{border-radius:4px}.ttdk-button[data-rounded=md]{border-radius:6px}.ttdk-button[data-rounded=lg]{border-radius:8px}.ttdk-button[data-rounded=full]{border-radius:9999px}.dark .ttdk-button,html.dark .ttdk-button,[data-mode=dark] .ttdk-button,[data-theme=dark] .ttdk-button{&[data-appearance=solid][data-variant=neutral],&[data-variant=neutral]:not([data-appearance]){background-color:var(--ttdk-bg-stay-black);border-color:var(--ttdk-bg-stay-black);color:var(--ttdk-text-icon-stay-white);&:hover:not(:disabled){color:var(--ttdk-text-icon-stay-white);background-color:#2f2f2f;border-color:#2f2f2f}}&[data-appearance=soft][data-variant=neutral]{background-color:var(--ttdk-color-neutral-900);border-color:var(--ttdk-stroke-strong);color:var(--ttdk-text-icon-primary);&:hover:not(:disabled){background-color:var(--ttdk-color-neutral-800);border-color:var(--ttdk-stroke-stay-white);color:var(--ttdk-text-icon-primary)}}&[data-appearance=outline][data-variant=neutral]{background-color:var(--ttdk-bg-stay-black);border-color:var(--ttdk-stroke-stay-white);color:var(--ttdk-text-icon-primary);&:hover:not(:disabled){color:var(--ttdk-text-icon-primary);background-color:#ffffff14}}&[data-appearance=link][data-variant=neutral]{color:var(--ttdk-text-icon-primary);&:hover:not(:disabled){color:var(--ttdk-text-icon-stay-white)}}&[data-appearance=soft][data-variant=primary]{background-color:var(--ttdk-brand-subtle-dark);border-color:var(--ttdk-brand-default);color:var(--ttdk-brand-default);&:hover:not(:disabled){border-color:var(--ttdk-brand-default);color:var(--ttdk-brand-default);background-color:#16b3ac40}}&[data-appearance=outline][data-variant=primary]{border-color:var(--ttdk-brand-default);color:var(--ttdk-brand-default);background-color:#0000;&:hover:not(:disabled){background-color:#16b3ac26}}&[data-appearance=soft][data-variant=info]{background-color:var(--ttdk-bg-status-info-subtle);border-color:var(--ttdk-stroke-status-info);color:var(--ttdk-text-icon-status-info);&:hover:not(:disabled){background-color:#2196f340}}&[data-appearance=soft][data-variant=warning]{background-color:var(--ttdk-bg-status-warning-subtle);border-color:var(--ttdk-stroke-status-warning);color:var(--ttdk-text-icon-status-warning);&:hover:not(:disabled){background-color:#fb8c0040}}&[data-appearance=soft][data-variant=danger]{background-color:var(--ttdk-bg-status-error-subtle);border-color:var(--ttdk-stroke-status-error);color:var(--ttdk-text-icon-status-error);&:hover:not(:disabled){background-color:#d0021b40}}&[data-appearance=ghost][data-variant=primary]{color:var(--ttdk-brand-default);background-color:#0000;border-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-brand-subtle-dark);color:var(--ttdk-brand-default);border-color:#0000}}&[data-appearance=ghost][data-variant=neutral]{color:var(--ttdk-text-icon-primary);background-color:#0000;border-color:#0000;&:hover:not(:disabled){background-color:var(--ttdk-color-neutral-800);color:var(--ttdk-text-icon-primary);border-color:#0000}}&[data-appearance=ghost][data-variant=info]{color:var(--ttdk-text-icon-status-info);background-color:#0000;border-color:#0000;&:hover:not(:disabled){color:var(--ttdk-text-icon-status-info);background-color:#2196f340;border-color:#0000}}&[data-appearance=ghost][data-variant=warning]{color:var(--ttdk-text-icon-status-warning);background-color:#0000;border-color:#0000;&:hover:not(:disabled){color:var(--ttdk-text-icon-status-warning);background-color:#fb8c0040;border-color:#0000}}&[data-appearance=ghost][data-variant=danger]{color:var(--ttdk-text-icon-status-error);background-color:#0000;border-color:#0000;&:hover:not(:disabled){color:var(--ttdk-text-icon-status-error);background-color:#d0021b40;border-color:#0000}}&[data-appearance=solid][data-variant=primary],&[data-variant=primary]:not([data-appearance]),&[data-appearance=solid][data-variant=info],&[data-variant=info]:not([data-appearance]),&[data-appearance=solid][data-variant=danger],&[data-variant=danger]:not([data-appearance]){color:#fff;&:hover:not(:disabled){color:#fff}}&[data-appearance=solid][data-variant=warning],&[data-variant=warning]:not([data-appearance]){color:var(--ttdk-color-black);&:hover:not(:disabled){color:var(--ttdk-color-black)}}&[data-appearance=solid][data-variant=warning]:hover:not(:disabled),&[data-variant=warning]:not([data-appearance]):hover:not(:disabled){background-color:var(--ttdk-bg-status-warning-strong)}&[data-appearance=solid][data-variant=info]:hover:not(:disabled),&[data-variant=info]:not([data-appearance]):hover:not(:disabled){background-color:var(--ttdk-bg-status-info-strong)}&[data-appearance=solid][data-variant=danger]:hover:not(:disabled),&[data-variant=danger]:not([data-appearance]):hover:not(:disabled){background-color:var(--ttdk-bg-status-error-strong)}&:disabled:not([data-loading=true]),&[disabled]:not([data-loading=true]),&[data-disabled=true]:not([data-loading=true]),&[data-variant=disabled]{background-color:var(--ttdk-bg-secondary-disabled)!important;color:var(--ttdk-text-icon-disabled)!important;border-color:#0000!important}}[data-sonner-toasters]{font-family:var(--ttdk-font-sans);-webkit-font-smoothing:antialiased}@keyframes ttdk-button-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}
@@ -0,0 +1,287 @@
1
+ "use client";
2
+ import * as React from "react";
3
+
4
+ export type ButtonUiProps = UiProps;
5
+ export interface ButtonProps {
6
+ /**
7
+ * Inline CSS style kustom.
8
+ */
9
+ style?: React.CSSProperties;
10
+
11
+ /**
12
+ * Varian warna semantik tombol:
13
+ * - `'primary'`: Teal utama.
14
+ * - `'info'`: Biru informasi.
15
+ * - `'warning'`: Kuning peringatan.
16
+ * - `'danger'`: Merah bahaya.
17
+ * - `'neutral'`: Abu-abu netral.
18
+ * - `'disabled'`: Tombol non-aktif.
19
+ *
20
+ * @default 'primary'
21
+ */
22
+ variant?: "primary" | "info" | "warning" | "danger" | "neutral" | "disabled";
23
+
24
+ /**
25
+ * Gaya tampilan visual tombol:
26
+ * - `'solid'`: Latar belakang warna solid pekat (default).
27
+ * - `'soft'`: Latar belakang warna transparan lembut.
28
+ * - `'outline'`: Garis tepi dengan latar belakang transparan.
29
+ * - `'link'`: Teks tautan tanpa border/latar, dengan garis bawah saat hover.
30
+ * - `'ghost'`: Transparan tanpa outline/border, dengan latar lembut saat hover.
31
+ *
32
+ * @default 'solid'
33
+ */
34
+ appearance?: "solid" | "soft" | "outline" | "link" | "ghost";
35
+
36
+ /**
37
+ * Tipe tombol HTML native.
38
+ * @default 'button'
39
+ */
40
+ type?: "button" | "submit" | "reset";
41
+
42
+ /**
43
+ * Skala ukuran tombol:
44
+ * - `'sm'`: 36px
45
+ * - `'md'`: 48px (standar)
46
+ * - `'lg'`: 56px
47
+ *
48
+ * @default 'md'
49
+ */
50
+ size?: "sm" | "md" | "lg";
51
+
52
+ /**
53
+ * Mode negatif — kontras tinggi di atas latar gelap.
54
+ * @default false
55
+ */
56
+ negative?: boolean;
57
+
58
+ /**
59
+ * Radius sudut tombol.
60
+ * - `'none'`: 0px
61
+ * - `'sm'`: 4px
62
+ * - `'md'`: 8px (standar)
63
+ * - `'lg'`: 12px
64
+ * - `'full'`: 9999px (pill)
65
+ *
66
+ * @default 'md'
67
+ */
68
+ rounded?: "none" | "sm" | "md" | "lg" | "full";
69
+
70
+ /**
71
+ * Mode tombol ikon persegi (aspek rasio 1:1).
72
+ * @default false
73
+ */
74
+ iconOnly?: boolean;
75
+
76
+ /**
77
+ * Full-width — melebar 100% dari container.
78
+ * @default false
79
+ */
80
+ block?: boolean;
81
+
82
+ /**
83
+ * Tampilkan spinner & nonaktifkan tombol saat proses async.
84
+ * @default false
85
+ */
86
+ loading?: boolean;
87
+
88
+ /**
89
+ * Nonaktifkan tombol dari interaksi pengguna.
90
+ * @default false
91
+ */
92
+ disabled?: boolean;
93
+
94
+ /**
95
+ * Warna kustom untuk ikon di dalam tombol (misal: '#fff', '#0968F6').
96
+ */
97
+ iconColor?: string;
98
+
99
+ /**
100
+ * Ukuran kustom untuk ikon di dalam tombol (misal: '16px', '20px').
101
+ */
102
+ iconSize?: string;
103
+
104
+ /**
105
+ * Kustomisasi visual — seperti style object tapi dengan support pseudo-class.
106
+ *
107
+ * @example
108
+ * ```tsx
109
+ * <Button
110
+ * ui={{
111
+ * background: '#7c3aed',
112
+ * color: 'white',
113
+ * borderRadius: '99px',
114
+ * hover: {
115
+ * background: '#6d28d9',
116
+ * transform: 'scale(1.02)',
117
+ * },
118
+ * active: {
119
+ * opacity: '0.9',
120
+ * }
121
+ * }}
122
+ * />
123
+ * ```
124
+ */
125
+ ui?: UiProps;
126
+
127
+ /**
128
+ * Event handler saat tombol diklik.
129
+ */
130
+ onClick?: (event?: any) => void;
131
+
132
+ /**
133
+ * Class CSS kustom.
134
+ */
135
+ className?: string;
136
+
137
+ /**
138
+ * Konten tombol — teks, ikon, atau JSX.
139
+ */
140
+ children?: any;
141
+ }
142
+
143
+ import { buildUiVars, UiProps } from "../../core/types";
144
+
145
+ function Button(props: ButtonProps) {
146
+ return (
147
+ <button
148
+ className={`ttdk-button ${props.className || ""}`.trim()}
149
+ type={props.type || "button"}
150
+ data-variant={props.variant || "primary"}
151
+ data-appearance={props.appearance || "solid"}
152
+ data-size={props.size || "md"}
153
+ data-negative={props.negative ? "true" : undefined}
154
+ data-rounded={props.rounded}
155
+ data-icon-only={props.iconOnly}
156
+ data-block={props.block ? "true" : undefined}
157
+ data-loading={props.loading ? "true" : undefined}
158
+ disabled={props.disabled || props.variant === "disabled" || props.loading}
159
+ style={{
160
+ ...buildUiVars(props.ui),
161
+ ...(props.iconColor
162
+ ? {
163
+ "--ttdk-ui-icon-color": props.iconColor,
164
+ }
165
+ : {}),
166
+ ...(props.iconSize
167
+ ? {
168
+ "--ttdk-ui-icon-size": props.iconSize,
169
+ }
170
+ : {}),
171
+ ...((props as any)["style"] || {}),
172
+ ...props.style,
173
+ }}
174
+ onClick={(event) => {
175
+ props.onClick?.(event);
176
+ }}
177
+ >
178
+ {props.loading ? (
179
+ <span className="ttdk-button-spinner" aria-hidden="true">
180
+ <svg viewBox="0 0 24 24">
181
+ <line
182
+ x1="12"
183
+ y1="2.5"
184
+ x2="12"
185
+ y2="6.5"
186
+ opacity="0.175"
187
+ transform="rotate(0 12 12)"
188
+ />
189
+ <line
190
+ x1="12"
191
+ y1="2.5"
192
+ x2="12"
193
+ y2="6.5"
194
+ opacity="0.25"
195
+ transform="rotate(30 12 12)"
196
+ />
197
+ <line
198
+ x1="12"
199
+ y1="2.5"
200
+ x2="12"
201
+ y2="6.5"
202
+ opacity="0.325"
203
+ transform="rotate(60 12 12)"
204
+ />
205
+ <line
206
+ x1="12"
207
+ y1="2.5"
208
+ x2="12"
209
+ y2="6.5"
210
+ opacity="0.4"
211
+ transform="rotate(90 12 12)"
212
+ />
213
+ <line
214
+ x1="12"
215
+ y1="2.5"
216
+ x2="12"
217
+ y2="6.5"
218
+ opacity="0.475"
219
+ transform="rotate(120 12 12)"
220
+ />
221
+ <line
222
+ x1="12"
223
+ y1="2.5"
224
+ x2="12"
225
+ y2="6.5"
226
+ opacity="0.55"
227
+ transform="rotate(150 12 12)"
228
+ />
229
+ <line
230
+ x1="12"
231
+ y1="2.5"
232
+ x2="12"
233
+ y2="6.5"
234
+ opacity="0.625"
235
+ transform="rotate(180 12 12)"
236
+ />
237
+ <line
238
+ x1="12"
239
+ y1="2.5"
240
+ x2="12"
241
+ y2="6.5"
242
+ opacity="0.7"
243
+ transform="rotate(210 12 12)"
244
+ />
245
+ <line
246
+ x1="12"
247
+ y1="2.5"
248
+ x2="12"
249
+ y2="6.5"
250
+ opacity="0.775"
251
+ transform="rotate(240 12 12)"
252
+ />
253
+ <line
254
+ x1="12"
255
+ y1="2.5"
256
+ x2="12"
257
+ y2="6.5"
258
+ opacity="0.85"
259
+ transform="rotate(270 12 12)"
260
+ />
261
+ <line
262
+ x1="12"
263
+ y1="2.5"
264
+ x2="12"
265
+ y2="6.5"
266
+ opacity="0.925"
267
+ transform="rotate(300 12 12)"
268
+ />
269
+ <line
270
+ x1="12"
271
+ y1="2.5"
272
+ x2="12"
273
+ y2="6.5"
274
+ opacity="1"
275
+ transform="rotate(330 12 12)"
276
+ />
277
+ </svg>
278
+ </span>
279
+ ) : null}
280
+ <>{props.children}</>
281
+ </button>
282
+ );
283
+ }
284
+
285
+ export default Button;
286
+
287
+ export { Button };
@@ -0,0 +1,2 @@
1
+ export { default as Button } from './button';
2
+ export { default } from './button'
@@ -0,0 +1,177 @@
1
+ {
2
+ "name": "@ttdk-design-system/button",
3
+ "component": "Button",
4
+ "folder": "button",
5
+ "description": "TTDK Button component with multi-theme support.",
6
+ "stylesheets": [
7
+ {
8
+ "theme": "common",
9
+ "file": "button.css",
10
+ "importPath": "web/button/button.css"
11
+ }
12
+ ],
13
+ "props": {
14
+ "style": {
15
+ "name": "style",
16
+ "type": "any",
17
+ "optional": true,
18
+ "default": null,
19
+ "description": "Inline CSS style kustom.",
20
+ "example": null,
21
+ "param": null
22
+ },
23
+ "variant": {
24
+ "name": "variant",
25
+ "type": "| 'primary'\n | 'info'\n | 'warning'\n | 'danger'\n | 'neutral'\n | 'disabled'",
26
+ "optional": true,
27
+ "default": "primary",
28
+ "description": "Varian warna semantik tombol: - `'primary'`: Teal utama. - `'info'`: Biru informasi. - `'warning'`: Kuning peringatan. - `'danger'`: Merah bahaya. - `'neutral'`: Abu-abu netral. - `'disabled'`: Tombol non-aktif.",
29
+ "example": null,
30
+ "param": null
31
+ },
32
+ "appearance": {
33
+ "name": "appearance",
34
+ "type": "'solid' | 'soft' | 'outline' | 'link' | 'ghost'",
35
+ "optional": true,
36
+ "default": "solid",
37
+ "description": "Gaya tampilan visual tombol: - `'solid'`: Latar belakang warna solid pekat (default). - `'soft'`: Latar belakang warna transparan lembut. - `'outline'`: Garis tepi dengan latar belakang transparan. - `'link'`: Teks tautan tanpa border/latar, dengan garis bawah saat hover. - `'ghost'`: Transparan tanpa outline/border, dengan latar lembut saat hover.",
38
+ "example": null,
39
+ "param": null
40
+ },
41
+ "type": {
42
+ "name": "type",
43
+ "type": "'button' | 'submit' | 'reset'",
44
+ "optional": true,
45
+ "default": "button",
46
+ "description": "Tipe tombol HTML native.",
47
+ "example": null,
48
+ "param": null
49
+ },
50
+ "size": {
51
+ "name": "size",
52
+ "type": "'sm' | 'md' | 'lg'",
53
+ "optional": true,
54
+ "default": "md",
55
+ "description": "Skala ukuran tombol: - `'sm'`: 36px - `'md'`: 48px (standar) - `'lg'`: 56px",
56
+ "example": null,
57
+ "param": null
58
+ },
59
+ "negative": {
60
+ "name": "negative",
61
+ "type": "boolean",
62
+ "optional": true,
63
+ "default": "false",
64
+ "description": "Mode negatif — kontras tinggi di atas latar gelap.",
65
+ "example": null,
66
+ "param": null
67
+ },
68
+ "rounded": {
69
+ "name": "rounded",
70
+ "type": "'none' | 'sm' | 'md' | 'lg' | 'full'",
71
+ "optional": true,
72
+ "default": "md",
73
+ "description": "Radius sudut tombol. - `'none'`: 0px - `'sm'`: 4px - `'md'`: 8px (standar) - `'lg'`: 12px - `'full'`: 9999px (pill)",
74
+ "example": null,
75
+ "param": null
76
+ },
77
+ "iconOnly": {
78
+ "name": "iconOnly",
79
+ "type": "boolean",
80
+ "optional": true,
81
+ "default": "false",
82
+ "description": "Mode tombol ikon persegi (aspek rasio 1:1).",
83
+ "example": null,
84
+ "param": null
85
+ },
86
+ "block": {
87
+ "name": "block",
88
+ "type": "boolean",
89
+ "optional": true,
90
+ "default": "false",
91
+ "description": "Full-width — melebar 100% dari container.",
92
+ "example": null,
93
+ "param": null
94
+ },
95
+ "loading": {
96
+ "name": "loading",
97
+ "type": "boolean",
98
+ "optional": true,
99
+ "default": "false",
100
+ "description": "Tampilkan spinner & nonaktifkan tombol saat proses async.",
101
+ "example": null,
102
+ "param": null
103
+ },
104
+ "disabled": {
105
+ "name": "disabled",
106
+ "type": "boolean",
107
+ "optional": true,
108
+ "default": "false",
109
+ "description": "Nonaktifkan tombol dari interaksi pengguna.",
110
+ "example": null,
111
+ "param": null
112
+ },
113
+ "iconColor": {
114
+ "name": "iconColor",
115
+ "type": "string",
116
+ "optional": true,
117
+ "default": null,
118
+ "description": "Warna kustom untuk ikon di dalam tombol (misal: '#fff', '#0968F6').",
119
+ "example": null,
120
+ "param": null
121
+ },
122
+ "iconSize": {
123
+ "name": "iconSize",
124
+ "type": "string",
125
+ "optional": true,
126
+ "default": null,
127
+ "description": "Ukuran kustom untuk ikon di dalam tombol (misal: '16px', '20px').",
128
+ "example": null,
129
+ "param": null
130
+ },
131
+ "ui": {
132
+ "name": "ui",
133
+ "type": "UiProps",
134
+ "optional": true,
135
+ "default": null,
136
+ "description": "Kustomisasi visual — seperti style object tapi dengan support pseudo-class. ```tsx <Button ui={{ background: '#7c3aed', color: 'white', borderRadius: '99px', hover: { background: '#6d28d9', transform: 'scale(1.02)', }, active: { opacity: '0.9', } }} /> ```",
137
+ "example": null,
138
+ "param": null
139
+ },
140
+ "onClick": {
141
+ "name": "onClick",
142
+ "type": "(event?: any) => void",
143
+ "optional": true,
144
+ "default": null,
145
+ "description": "Event handler saat tombol diklik.",
146
+ "example": null,
147
+ "param": null
148
+ },
149
+ "className": {
150
+ "name": "className",
151
+ "type": "string",
152
+ "optional": true,
153
+ "default": null,
154
+ "description": "Class CSS kustom.",
155
+ "example": null,
156
+ "param": null
157
+ },
158
+ "children": {
159
+ "name": "children",
160
+ "type": "any",
161
+ "optional": true,
162
+ "default": null,
163
+ "description": "Konten tombol — teks, ikon, atau JSX.",
164
+ "example": null,
165
+ "param": null
166
+ }
167
+ },
168
+ "subInterfaces": {},
169
+ "supportedFrameworks": [
170
+ "react",
171
+ "vue",
172
+ "svelte"
173
+ ],
174
+ "themes": [
175
+ "tw"
176
+ ]
177
+ }
@@ -0,0 +1,151 @@
1
+ # <Calendar /> — TTDK Component Reference
2
+
3
+ TTDK Calendar component with multi-theme support.
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/calendar/calendar.css";`
8
+
9
+ ## 2. Subpath Component Import
10
+ ```ts
11
+ // React
12
+ import Calendar from "@ttdk-design-system/library-react/web/calendar";
13
+
14
+ // Vue 3
15
+ import Calendar from "@ttdk-design-system/library-vue/web/calendar";
16
+
17
+ // Svelte
18
+ import Calendar from "@ttdk-design-system/library-svelte/web/calendar";
19
+ ```
20
+
21
+ ## 3. Props & API Reference
22
+
23
+ | Prop | Type | Default | Description |
24
+ | :--- | :--- | :--- | :--- |
25
+ | `value?` | `any` | `-` | Nilai tanggal terpilih pada mode controlled. - Single: string ('YYYY-MM-DD') atau Date - Range: { start: string | Date | null, end: string | Date | null } - Multiple: string[] atau Date[] |
26
+ | `defaultValue?` | `any` | `-` | Nilai awal tanggal terpilih pada mode uncontrolled. |
27
+ | `id?` | `string` | `-` | Atribut ID unik untuk elemen root kalender. |
28
+ | `range?` | `boolean` | `false` | Mengaktifkan mode pemilihan rentang tanggal (start date - end date). |
29
+ | `multiple?` | `boolean` | `false` | Mengaktifkan mode pemilihan banyak tanggal sekaligus. |
30
+ | `min?` | `string | Date` | `-` | Batas tanggal paling awal yang dapat dipilih. |
31
+ | `minValue?` | `string | Date` | `-` | Alias untuk min (kompatibel Nuxt UI: min-value). |
32
+ | `max?` | `string | Date` | `-` | Batas tanggal paling akhir yang dapat dipilih. |
33
+ | `maxValue?` | `string | Date` | `-` | Alias untuk max (kompatibel Nuxt UI: max-value). |
34
+ | `isDateDisabled?` | `(date: Date) => boolean` | `-` | Fungsi untuk menonaktifkan tanggal tertentu secara spesifik (misal: hari libur / akhir pekan). |
35
+ | `isDateUnavailable?` | `(date: Date) => boolean` | `-` | Fungsi untuk menandai tanggal tidak tersedia (ditampilkan coret strikethrough). |
36
+ | `numberOfMonths?` | `number` | `1` | Jumlah bulan yang ditampilkan secara berdampingan. |
37
+ | `weekStartsOn?` | `0 | 1 | 2 | 3 | 4 | 5 | 6` | `1` | Hari awal dalam seminggu: - 0 = Minggu (Sunday) - 1 = Senin (Monday) |
38
+ | `locale?` | `string` | `id-ID` | Kode lokal bahasa kalender (misal: 'id-ID', 'en-US'). |
39
+ | `month?` | `number` | `-` | Bulan yang sedang ditampilkan (1 - 12) pada mode navigasi controlled. |
40
+ | `year?` | `number` | `-` | Tahun yang sedang ditampilkan (misal: 2026) pada mode navigasi controlled. |
41
+ | `defaultMonth?` | `number` | `-` | Bulan awal yang sedang ditampilkan (1 - 12). |
42
+ | `defaultYear?` | `number` | `-` | Tahun awal yang sedang ditampilkan. |
43
+ | `yearControls?` | `boolean` | `true` | Menampilkan tombol navigasi lompat tahun (<< dan >>). |
44
+ | `showOutsideDays?` | `boolean` | `true` | Menampilkan hari-hari redup di luar bulan yang aktif (leading & trailing days). |
45
+ | `fixedWeeks?` | `boolean` | `true` | Selalu merender 6 baris minggu agar tinggi kalender konsisten stabil antar bulan. |
46
+ | `dateMarkers?` | `DateMarker[]` | `-` | Daftar penanda agenda / jadwal faskes pada tanggal tertentu. |
47
+ | `size?` | `'sm' | 'md' | 'lg'` | `md` | Skala ukuran kalender (sm: kompak 32px, md: standar 38px, lg: besar 44px). |
48
+ | `rounded?` | `'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'` | `md` | Radius sudut kelengkungan container kalender. |
49
+ | `variant?` | `'default' | 'bordered' | 'card' | 'flat'` | `bordered` | Varian visual tampilan kalender: - 'default': Bersih dengan background putih/gelap. - 'bordered': Dengan bingkai border solid luar. - 'card': Dengan elevasi bayangan halus kartu. - 'flat': Minimalis tanpa border dan tanpa shadow. |
50
+ | `disabled?` | `boolean` | `false` | Menonaktifkan seluruh kalender dari interaksi. |
51
+ | `readOnly?` | `boolean` | `false` | Mode hanya-baca (read-only). |
52
+ | `onValueChange?` | `(value: any) => void` | `-` | Callback event saat nilai tanggal berubah. |
53
+ | `onChange?` | `(event: any) => void` | `-` | Callback event native saat nilai berubah. |
54
+ | `onMonthChange?` | `(month: number, year: number) => void` | `-` | Callback saat navigasi bulan atau tahun berubah. |
55
+ | `onYearChange?` | `(month: number, year: number) => void` | `-` | Callback saat tahun tampilan kalender berubah. |
56
+ | `defaultViewMode?` | `'day' | 'month' | 'year'` | `day` | Mode tampilan awal kalender ('day', 'month', 'year'). |
57
+ | `viewMode?` | `'day' | 'month' | 'year'` | `-` | Mode tampilan kalender saat ini ('day', 'month', 'year') untuk mode controlled. |
58
+ | `onViewModeChange?` | `(mode: 'day' | 'month' | 'year') => void` | `-` | Callback saat mode tampilan kalender berubah ('day', 'month', 'year'). |
59
+ | `className?` | `string` | `-` | Class CSS kustom untuk container utama. |
60
+ | `style?` | `any` | `-` | Inline style CSS kustom untuk container utama. |
61
+ | `headerClass?` | `string` | `-` | Class CSS kustom untuk header kalender. |
62
+ | `headerStyle?` | `UiProps` | `-` | Inline style kustom untuk header kalender. |
63
+ | `navBtnClass?` | `string` | `-` | Class CSS kustom untuk tombol navigasi. |
64
+ | `navBtnStyle?` | `UiProps` | `-` | Inline style kustom untuk tombol navigasi. |
65
+ | `cellClass?` | `string` | `-` | Class CSS kustom untuk cell tanggal. |
66
+ | `cellStyle?` | `UiProps` | `-` | Inline style kustom untuk cell tanggal. |
67
+ | `ui?` | `UiProps` | `-` | Kustomisasi visual granular UiProps. |
68
+
69
+ ### Sub-interface: `DateRange`
70
+
71
+ | Field | Type | Default | Description |
72
+ | :--- | :--- | :--- | :--- |
73
+ | `start` | `string | Date | null` | `-` | |
74
+ | `end` | `string | Date | null` | `-` | |
75
+
76
+ ### Sub-interface: `DateMarker`
77
+
78
+ | Field | Type | Default | Description |
79
+ | :--- | :--- | :--- | :--- |
80
+ | `date` | `string` | `-` | |
81
+ | `color?` | `string` | `-` | |
82
+ | `tooltip?` | `string` | `-` | |
83
+ | `dot?` | `boolean` | `-` | |
84
+
85
+ ## 4. Usage Examples
86
+
87
+ ### React Example
88
+ ```tsx
89
+ import { useState } from "react";
90
+ import Calendar from "@ttdk-design-system/library-react/web/calendar";
91
+ import "@ttdk-design-system/library-react/web/calendar/calendar.css";
92
+
93
+ export function Example() {
94
+ const [selectedDate, setSelectedDate] = useState("2026-10-13");
95
+
96
+ return (
97
+ <div style={{ maxWidth: '320px' }}>
98
+ <Calendar
99
+ value={selectedDate}
100
+ onChange={(date) => setSelectedDate(date)}
101
+ />
102
+ <div style={{ marginTop: '12px', fontSize: '14px' }}>
103
+ Tanggal terpilih: <strong>{selectedDate}</strong>
104
+ </div>
105
+ </div>
106
+ );
107
+ }
108
+ ```
109
+
110
+ ### Vue 3 Example
111
+ ```vue
112
+ <script setup lang="ts">
113
+ import { ref } from "vue";
114
+ import Calendar from "@ttdk-design-system/library-vue/web/calendar";
115
+ import "@ttdk-design-system/library-vue/web/calendar/calendar.css";
116
+
117
+ const selectedDate = ref("2026-10-13");
118
+ </script>
119
+
120
+ <template>
121
+ <div style="max-width: 320px;">
122
+ <Calendar
123
+ :value="selectedDate"
124
+ @change="(date: any) => (selectedDate = date)"
125
+ />
126
+ <div style="margin-top: 12px; font-size: 14px;">
127
+ Tanggal terpilih: <strong>{{ selectedDate }}</strong>
128
+ </div>
129
+ </div>
130
+ </template>
131
+ ```
132
+
133
+ ### Svelte Example
134
+ ```svelte
135
+ <script lang="ts">
136
+ import Calendar from "@ttdk-design-system/library-svelte/web/calendar";
137
+ import "@ttdk-design-system/library-svelte/web/calendar/calendar.css";
138
+
139
+ let selectedDate = "2026-10-13";
140
+ </script>
141
+
142
+ <div style="max-width: 320px;">
143
+ <Calendar
144
+ value={selectedDate}
145
+ on:change={(e) => (selectedDate = e.detail)}
146
+ />
147
+ <div style="margin-top: 12px; font-size: 14px;">
148
+ Tanggal terpilih: <strong>{selectedDate}</strong>
149
+ </div>
150
+ </div>
151
+ ```