@ezpg/app-ui 0.1.0 → 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.
Files changed (354) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/lib/module/blocks/brand-profile-card/brand-profile-card.js +0 -2
  3. package/lib/module/blocks/brand-profile-card/brand-profile-card.js.map +1 -1
  4. package/lib/module/blocks/bulk-ship-list/bulk-ship-list.js +190 -0
  5. package/lib/module/blocks/bulk-ship-list/bulk-ship-list.js.map +1 -0
  6. package/lib/module/blocks/bulk-ship-list/index.js +4 -0
  7. package/lib/module/blocks/bulk-ship-list/index.js.map +1 -0
  8. package/lib/module/blocks/claim-row/claim-row.js +34 -35
  9. package/lib/module/blocks/claim-row/claim-row.js.map +1 -1
  10. package/lib/module/blocks/claim-row/index.js +1 -1
  11. package/lib/module/blocks/claim-row/index.js.map +1 -1
  12. package/lib/module/blocks/color-swatch-picker/color-swatch-picker.js +0 -2
  13. package/lib/module/blocks/color-swatch-picker/color-swatch-picker.js.map +1 -1
  14. package/lib/module/blocks/copy-variant-picker/copy-variant-picker.js +1 -3
  15. package/lib/module/blocks/copy-variant-picker/copy-variant-picker.js.map +1 -1
  16. package/lib/module/blocks/credit-wallet/credit-wallet.js +3 -5
  17. package/lib/module/blocks/credit-wallet/credit-wallet.js.map +1 -1
  18. package/lib/module/blocks/generation-progress/generation-progress.js +157 -0
  19. package/lib/module/blocks/generation-progress/generation-progress.js.map +1 -0
  20. package/lib/module/blocks/generation-progress/index.js +4 -0
  21. package/lib/module/blocks/generation-progress/index.js.map +1 -0
  22. package/lib/module/blocks/image-grid/image-grid.js +20 -16
  23. package/lib/module/blocks/image-grid/image-grid.js.map +1 -1
  24. package/lib/module/blocks/index.js +3 -0
  25. package/lib/module/blocks/index.js.map +1 -1
  26. package/lib/module/blocks/internal/card.js +49 -10
  27. package/lib/module/blocks/internal/card.js.map +1 -1
  28. package/lib/module/blocks/internal/format.js +0 -6
  29. package/lib/module/blocks/internal/format.js.map +1 -1
  30. package/lib/module/blocks/invoice-row/invoice-row.js +3 -5
  31. package/lib/module/blocks/invoice-row/invoice-row.js.map +1 -1
  32. package/lib/module/blocks/logo-candidate-grid/logo-candidate-grid.js +0 -2
  33. package/lib/module/blocks/logo-candidate-grid/logo-candidate-grid.js.map +1 -1
  34. package/lib/module/blocks/oauth-buttons/oauth-buttons.js +0 -3
  35. package/lib/module/blocks/oauth-buttons/oauth-buttons.js.map +1 -1
  36. package/lib/module/blocks/option-editor/option-editor.js +22 -12
  37. package/lib/module/blocks/option-editor/option-editor.js.map +1 -1
  38. package/lib/module/blocks/order-card/order-card.js +11 -16
  39. package/lib/module/blocks/order-card/order-card.js.map +1 -1
  40. package/lib/module/blocks/plan-card/plan-card.js +9 -5
  41. package/lib/module/blocks/plan-card/plan-card.js.map +1 -1
  42. package/lib/module/blocks/product-list-empty/product-list-empty.js +0 -2
  43. package/lib/module/blocks/product-list-empty/product-list-empty.js.map +1 -1
  44. package/lib/module/blocks/review-row/review-row.js +0 -8
  45. package/lib/module/blocks/review-row/review-row.js.map +1 -1
  46. package/lib/module/blocks/sales-chart/sales-chart.js +1 -3
  47. package/lib/module/blocks/sales-chart/sales-chart.js.map +1 -1
  48. package/lib/module/blocks/selection-bar/index.js +4 -0
  49. package/lib/module/blocks/selection-bar/index.js.map +1 -0
  50. package/lib/module/blocks/selection-bar/selection-bar.js +69 -0
  51. package/lib/module/blocks/selection-bar/selection-bar.js.map +1 -0
  52. package/lib/module/blocks/service-state-banner/service-state-banner.js +12 -6
  53. package/lib/module/blocks/service-state-banner/service-state-banner.js.map +1 -1
  54. package/lib/module/blocks/shipping-tracking-row/shipping-tracking-row.js +0 -2
  55. package/lib/module/blocks/shipping-tracking-row/shipping-tracking-row.js.map +1 -1
  56. package/lib/module/blocks/site-preview-frame/site-preview-frame.js +12 -2
  57. package/lib/module/blocks/site-preview-frame/site-preview-frame.js.map +1 -1
  58. package/lib/module/blocks/stat-card/stat-card.js +1 -3
  59. package/lib/module/blocks/stat-card/stat-card.js.map +1 -1
  60. package/lib/module/blocks/step-screen/step-screen.js +0 -2
  61. package/lib/module/blocks/step-screen/step-screen.js.map +1 -1
  62. package/lib/module/blocks/supply-item-card/supply-item-card.js +0 -6
  63. package/lib/module/blocks/supply-item-card/supply-item-card.js.map +1 -1
  64. package/lib/module/charts/line-chart.js +10 -1
  65. package/lib/module/charts/line-chart.js.map +1 -1
  66. package/lib/module/charts/scale.js +0 -6
  67. package/lib/module/charts/scale.js.map +1 -1
  68. package/lib/module/charts/sparkline.js +0 -1
  69. package/lib/module/charts/sparkline.js.map +1 -1
  70. package/lib/module/charts/summary.js +0 -1
  71. package/lib/module/charts/summary.js.map +1 -1
  72. package/lib/module/components/button/button.js +3 -3
  73. package/lib/module/components/button/button.js.map +1 -1
  74. package/lib/module/components/chip/chip.js +14 -0
  75. package/lib/module/components/chip/chip.js.map +1 -1
  76. package/lib/module/components/chip-group/chip-group.js +1 -0
  77. package/lib/module/components/chip-group/chip-group.js.map +1 -1
  78. package/lib/module/components/dialog/dialog.js +2 -4
  79. package/lib/module/components/dialog/dialog.js.map +1 -1
  80. package/lib/module/components/divider/divider.js +0 -1
  81. package/lib/module/components/divider/divider.js.map +1 -1
  82. package/lib/module/components/empty-state/empty-state.js +0 -10
  83. package/lib/module/components/empty-state/empty-state.js.map +1 -1
  84. package/lib/module/components/field/field.js +57 -8
  85. package/lib/module/components/field/field.js.map +1 -1
  86. package/lib/module/components/list-row/list-row.js.map +1 -1
  87. package/lib/module/components/photo/photo.js +0 -3
  88. package/lib/module/components/photo/photo.js.map +1 -1
  89. package/lib/module/components/price/price.js +1 -3
  90. package/lib/module/components/price/price.js.map +1 -1
  91. package/lib/module/components/progress-bar/index.js +4 -0
  92. package/lib/module/components/progress-bar/index.js.map +1 -0
  93. package/lib/module/components/progress-bar/progress-bar.js +92 -0
  94. package/lib/module/components/progress-bar/progress-bar.js.map +1 -0
  95. package/lib/module/components/search-field/search-field.js.map +1 -1
  96. package/lib/module/components/segmented-tabs/segmented-tabs.js.map +1 -1
  97. package/lib/module/components/sheet/sheet.js.map +1 -1
  98. package/lib/module/components/skeleton/skeleton.js +0 -1
  99. package/lib/module/components/skeleton/skeleton.js.map +1 -1
  100. package/lib/module/components/status-badge/status-badge.js +1 -1
  101. package/lib/module/components/status-badge/status-badge.js.map +1 -1
  102. package/lib/module/components/switch/switch.js +4 -3
  103. package/lib/module/components/switch/switch.js.map +1 -1
  104. package/lib/module/components/text/text.js +2 -2
  105. package/lib/module/components/text/text.js.map +1 -1
  106. package/lib/module/components/toast/toast.js +1 -9
  107. package/lib/module/components/toast/toast.js.map +1 -1
  108. package/lib/module/components/wizard-steps/wizard-steps.js +0 -2
  109. package/lib/module/components/wizard-steps/wizard-steps.js.map +1 -1
  110. package/lib/module/index.js +1 -0
  111. package/lib/module/index.js.map +1 -1
  112. package/lib/module/internal/glyphs.js +0 -4
  113. package/lib/module/internal/glyphs.js.map +1 -1
  114. package/lib/module/internal/icon.js +0 -2
  115. package/lib/module/internal/icon.js.map +1 -1
  116. package/lib/module/internal/overlay.js +0 -5
  117. package/lib/module/internal/overlay.js.map +1 -1
  118. package/lib/module/internal/pressable-base.js +0 -1
  119. package/lib/module/internal/pressable-base.js.map +1 -1
  120. package/lib/module/internal/use-reduced-motion.js +0 -4
  121. package/lib/module/internal/use-reduced-motion.js.map +1 -1
  122. package/lib/module/sortable/move.js +0 -1
  123. package/lib/module/sortable/move.js.map +1 -1
  124. package/lib/module/sortable/sortable-grid.js +0 -6
  125. package/lib/module/sortable/sortable-grid.js.map +1 -1
  126. package/lib/module/sortable/sortable-list.js +0 -1
  127. package/lib/module/sortable/sortable-list.js.map +1 -1
  128. package/lib/module/theme/base.js +108 -0
  129. package/lib/module/theme/base.js.map +1 -0
  130. package/lib/module/theme/create-theme.js +0 -6
  131. package/lib/module/theme/create-theme.js.map +1 -1
  132. package/lib/module/theme/theme-provider.js +0 -2
  133. package/lib/module/theme/theme-provider.js.map +1 -1
  134. package/lib/module/theme/tokens.js +10 -115
  135. package/lib/module/theme/tokens.js.map +1 -1
  136. package/lib/module/utils/color.js +0 -5
  137. package/lib/module/utils/color.js.map +1 -1
  138. package/lib/module/utils/styles.js +0 -5
  139. package/lib/module/utils/styles.js.map +1 -1
  140. package/lib/typescript/src/blocks/brand-profile-card/brand-profile-card.d.ts +0 -2
  141. package/lib/typescript/src/blocks/brand-profile-card/brand-profile-card.d.ts.map +1 -1
  142. package/lib/typescript/src/blocks/bulk-ship-list/bulk-ship-list.d.ts +24 -0
  143. package/lib/typescript/src/blocks/bulk-ship-list/bulk-ship-list.d.ts.map +1 -0
  144. package/lib/typescript/src/blocks/bulk-ship-list/index.d.ts +2 -0
  145. package/lib/typescript/src/blocks/bulk-ship-list/index.d.ts.map +1 -0
  146. package/lib/typescript/src/blocks/claim-row/claim-row.d.ts +5 -12
  147. package/lib/typescript/src/blocks/claim-row/claim-row.d.ts.map +1 -1
  148. package/lib/typescript/src/blocks/claim-row/index.d.ts +1 -1
  149. package/lib/typescript/src/blocks/claim-row/index.d.ts.map +1 -1
  150. package/lib/typescript/src/blocks/color-swatch-picker/color-swatch-picker.d.ts +0 -2
  151. package/lib/typescript/src/blocks/color-swatch-picker/color-swatch-picker.d.ts.map +1 -1
  152. package/lib/typescript/src/blocks/copy-variant-picker/copy-variant-picker.d.ts +0 -4
  153. package/lib/typescript/src/blocks/copy-variant-picker/copy-variant-picker.d.ts.map +1 -1
  154. package/lib/typescript/src/blocks/credit-wallet/credit-wallet.d.ts +1 -3
  155. package/lib/typescript/src/blocks/credit-wallet/credit-wallet.d.ts.map +1 -1
  156. package/lib/typescript/src/blocks/generation-progress/generation-progress.d.ts +17 -0
  157. package/lib/typescript/src/blocks/generation-progress/generation-progress.d.ts.map +1 -0
  158. package/lib/typescript/src/blocks/generation-progress/index.d.ts +2 -0
  159. package/lib/typescript/src/blocks/generation-progress/index.d.ts.map +1 -0
  160. package/lib/typescript/src/blocks/image-grid/image-grid.d.ts +0 -6
  161. package/lib/typescript/src/blocks/image-grid/image-grid.d.ts.map +1 -1
  162. package/lib/typescript/src/blocks/index.d.ts +3 -0
  163. package/lib/typescript/src/blocks/index.d.ts.map +1 -1
  164. package/lib/typescript/src/blocks/internal/card.d.ts +3 -2
  165. package/lib/typescript/src/blocks/internal/card.d.ts.map +1 -1
  166. package/lib/typescript/src/blocks/internal/format.d.ts +0 -3
  167. package/lib/typescript/src/blocks/internal/format.d.ts.map +1 -1
  168. package/lib/typescript/src/blocks/invoice-row/invoice-row.d.ts +0 -7
  169. package/lib/typescript/src/blocks/invoice-row/invoice-row.d.ts.map +1 -1
  170. package/lib/typescript/src/blocks/logo-candidate-grid/logo-candidate-grid.d.ts +0 -2
  171. package/lib/typescript/src/blocks/logo-candidate-grid/logo-candidate-grid.d.ts.map +1 -1
  172. package/lib/typescript/src/blocks/oauth-buttons/oauth-buttons.d.ts +0 -7
  173. package/lib/typescript/src/blocks/oauth-buttons/oauth-buttons.d.ts.map +1 -1
  174. package/lib/typescript/src/blocks/option-editor/option-editor.d.ts +3 -5
  175. package/lib/typescript/src/blocks/option-editor/option-editor.d.ts.map +1 -1
  176. package/lib/typescript/src/blocks/order-card/order-card.d.ts +4 -12
  177. package/lib/typescript/src/blocks/order-card/order-card.d.ts.map +1 -1
  178. package/lib/typescript/src/blocks/plan-card/plan-card.d.ts +2 -13
  179. package/lib/typescript/src/blocks/plan-card/plan-card.d.ts.map +1 -1
  180. package/lib/typescript/src/blocks/product-list-empty/product-list-empty.d.ts +0 -5
  181. package/lib/typescript/src/blocks/product-list-empty/product-list-empty.d.ts.map +1 -1
  182. package/lib/typescript/src/blocks/review-row/review-row.d.ts +0 -9
  183. package/lib/typescript/src/blocks/review-row/review-row.d.ts.map +1 -1
  184. package/lib/typescript/src/blocks/sales-chart/sales-chart.d.ts +0 -5
  185. package/lib/typescript/src/blocks/sales-chart/sales-chart.d.ts.map +1 -1
  186. package/lib/typescript/src/blocks/selection-bar/index.d.ts +2 -0
  187. package/lib/typescript/src/blocks/selection-bar/index.d.ts.map +1 -0
  188. package/lib/typescript/src/blocks/selection-bar/selection-bar.d.ts +12 -0
  189. package/lib/typescript/src/blocks/selection-bar/selection-bar.d.ts.map +1 -0
  190. package/lib/typescript/src/blocks/service-state-banner/service-state-banner.d.ts +3 -4
  191. package/lib/typescript/src/blocks/service-state-banner/service-state-banner.d.ts.map +1 -1
  192. package/lib/typescript/src/blocks/shipping-tracking-row/shipping-tracking-row.d.ts +0 -1
  193. package/lib/typescript/src/blocks/shipping-tracking-row/shipping-tracking-row.d.ts.map +1 -1
  194. package/lib/typescript/src/blocks/site-preview-frame/site-preview-frame.d.ts +3 -5
  195. package/lib/typescript/src/blocks/site-preview-frame/site-preview-frame.d.ts.map +1 -1
  196. package/lib/typescript/src/blocks/stat-card/stat-card.d.ts +0 -5
  197. package/lib/typescript/src/blocks/stat-card/stat-card.d.ts.map +1 -1
  198. package/lib/typescript/src/blocks/step-screen/step-screen.d.ts +0 -6
  199. package/lib/typescript/src/blocks/step-screen/step-screen.d.ts.map +1 -1
  200. package/lib/typescript/src/blocks/supply-item-card/supply-item-card.d.ts +0 -6
  201. package/lib/typescript/src/blocks/supply-item-card/supply-item-card.d.ts.map +1 -1
  202. package/lib/typescript/src/charts/line-chart.d.ts +1 -5
  203. package/lib/typescript/src/charts/line-chart.d.ts.map +1 -1
  204. package/lib/typescript/src/charts/scale.d.ts +0 -3
  205. package/lib/typescript/src/charts/scale.d.ts.map +1 -1
  206. package/lib/typescript/src/charts/sparkline.d.ts +0 -4
  207. package/lib/typescript/src/charts/sparkline.d.ts.map +1 -1
  208. package/lib/typescript/src/charts/summary.d.ts +0 -1
  209. package/lib/typescript/src/charts/summary.d.ts.map +1 -1
  210. package/lib/typescript/src/components/button/button.d.ts +1 -4
  211. package/lib/typescript/src/components/button/button.d.ts.map +1 -1
  212. package/lib/typescript/src/components/chip/chip.d.ts +2 -1
  213. package/lib/typescript/src/components/chip/chip.d.ts.map +1 -1
  214. package/lib/typescript/src/components/chip-group/chip-group.d.ts +1 -2
  215. package/lib/typescript/src/components/chip-group/chip-group.d.ts.map +1 -1
  216. package/lib/typescript/src/components/dialog/dialog.d.ts +2 -9
  217. package/lib/typescript/src/components/dialog/dialog.d.ts.map +1 -1
  218. package/lib/typescript/src/components/divider/divider.d.ts +0 -2
  219. package/lib/typescript/src/components/divider/divider.d.ts.map +1 -1
  220. package/lib/typescript/src/components/empty-state/empty-state.d.ts +0 -10
  221. package/lib/typescript/src/components/empty-state/empty-state.d.ts.map +1 -1
  222. package/lib/typescript/src/components/field/field.d.ts +3 -3
  223. package/lib/typescript/src/components/field/field.d.ts.map +1 -1
  224. package/lib/typescript/src/components/list-row/list-row.d.ts +0 -3
  225. package/lib/typescript/src/components/list-row/list-row.d.ts.map +1 -1
  226. package/lib/typescript/src/components/photo/photo.d.ts +0 -4
  227. package/lib/typescript/src/components/photo/photo.d.ts.map +1 -1
  228. package/lib/typescript/src/components/price/price.d.ts +0 -3
  229. package/lib/typescript/src/components/price/price.d.ts.map +1 -1
  230. package/lib/typescript/src/components/progress-bar/index.d.ts +2 -0
  231. package/lib/typescript/src/components/progress-bar/index.d.ts.map +1 -0
  232. package/lib/typescript/src/components/progress-bar/progress-bar.d.ts +9 -0
  233. package/lib/typescript/src/components/progress-bar/progress-bar.d.ts.map +1 -0
  234. package/lib/typescript/src/components/search-field/search-field.d.ts +0 -1
  235. package/lib/typescript/src/components/search-field/search-field.d.ts.map +1 -1
  236. package/lib/typescript/src/components/segmented-tabs/segmented-tabs.d.ts +0 -1
  237. package/lib/typescript/src/components/segmented-tabs/segmented-tabs.d.ts.map +1 -1
  238. package/lib/typescript/src/components/sheet/sheet.d.ts +0 -3
  239. package/lib/typescript/src/components/sheet/sheet.d.ts.map +1 -1
  240. package/lib/typescript/src/components/skeleton/skeleton.d.ts +0 -4
  241. package/lib/typescript/src/components/skeleton/skeleton.d.ts.map +1 -1
  242. package/lib/typescript/src/components/status-badge/status-badge.d.ts +1 -2
  243. package/lib/typescript/src/components/status-badge/status-badge.d.ts.map +1 -1
  244. package/lib/typescript/src/components/switch/switch.d.ts.map +1 -1
  245. package/lib/typescript/src/components/text/text.d.ts +1 -4
  246. package/lib/typescript/src/components/text/text.d.ts.map +1 -1
  247. package/lib/typescript/src/components/toast/toast.d.ts +1 -9
  248. package/lib/typescript/src/components/toast/toast.d.ts.map +1 -1
  249. package/lib/typescript/src/components/wizard-steps/wizard-steps.d.ts +0 -3
  250. package/lib/typescript/src/components/wizard-steps/wizard-steps.d.ts.map +1 -1
  251. package/lib/typescript/src/index.d.ts +1 -0
  252. package/lib/typescript/src/index.d.ts.map +1 -1
  253. package/lib/typescript/src/internal/glyphs.d.ts +0 -1
  254. package/lib/typescript/src/internal/glyphs.d.ts.map +1 -1
  255. package/lib/typescript/src/internal/icon.d.ts +0 -1
  256. package/lib/typescript/src/internal/icon.d.ts.map +1 -1
  257. package/lib/typescript/src/internal/overlay.d.ts +0 -4
  258. package/lib/typescript/src/internal/overlay.d.ts.map +1 -1
  259. package/lib/typescript/src/internal/pressable-base.d.ts +0 -3
  260. package/lib/typescript/src/internal/pressable-base.d.ts.map +1 -1
  261. package/lib/typescript/src/internal/use-reduced-motion.d.ts +0 -1
  262. package/lib/typescript/src/internal/use-reduced-motion.d.ts.map +1 -1
  263. package/lib/typescript/src/sortable/move.d.ts +0 -1
  264. package/lib/typescript/src/sortable/move.d.ts.map +1 -1
  265. package/lib/typescript/src/sortable/sortable-grid.d.ts +0 -12
  266. package/lib/typescript/src/sortable/sortable-grid.d.ts.map +1 -1
  267. package/lib/typescript/src/sortable/sortable-list.d.ts +0 -1
  268. package/lib/typescript/src/sortable/sortable-list.d.ts.map +1 -1
  269. package/lib/typescript/src/theme/base.d.ts +106 -0
  270. package/lib/typescript/src/theme/base.d.ts.map +1 -0
  271. package/lib/typescript/src/theme/create-theme.d.ts +0 -4
  272. package/lib/typescript/src/theme/create-theme.d.ts.map +1 -1
  273. package/lib/typescript/src/theme/theme-provider.d.ts +0 -3
  274. package/lib/typescript/src/theme/theme-provider.d.ts.map +1 -1
  275. package/lib/typescript/src/theme/tokens.d.ts.map +1 -1
  276. package/lib/typescript/src/types/index.d.ts +2 -9
  277. package/lib/typescript/src/types/index.d.ts.map +1 -1
  278. package/lib/typescript/src/utils/color.d.ts +0 -2
  279. package/lib/typescript/src/utils/color.d.ts.map +1 -1
  280. package/lib/typescript/src/utils/styles.d.ts +0 -5
  281. package/lib/typescript/src/utils/styles.d.ts.map +1 -1
  282. package/package.json +1 -1
  283. package/src/blocks/brand-profile-card/brand-profile-card.tsx +0 -2
  284. package/src/blocks/bulk-ship-list/bulk-ship-list.tsx +187 -0
  285. package/src/blocks/bulk-ship-list/index.ts +8 -0
  286. package/src/blocks/claim-row/claim-row.tsx +67 -54
  287. package/src/blocks/claim-row/index.ts +1 -0
  288. package/src/blocks/color-swatch-picker/color-swatch-picker.tsx +0 -2
  289. package/src/blocks/copy-variant-picker/copy-variant-picker.tsx +1 -5
  290. package/src/blocks/credit-wallet/credit-wallet.tsx +20 -14
  291. package/src/blocks/generation-progress/generation-progress.tsx +180 -0
  292. package/src/blocks/generation-progress/index.ts +6 -0
  293. package/src/blocks/image-grid/image-grid.tsx +10 -14
  294. package/src/blocks/index.tsx +3 -0
  295. package/src/blocks/internal/card.tsx +47 -3
  296. package/src/blocks/internal/format.ts +0 -3
  297. package/src/blocks/invoice-row/invoice-row.tsx +3 -10
  298. package/src/blocks/logo-candidate-grid/logo-candidate-grid.tsx +0 -2
  299. package/src/blocks/oauth-buttons/oauth-buttons.tsx +0 -8
  300. package/src/blocks/option-editor/option-editor.tsx +24 -10
  301. package/src/blocks/order-card/order-card.tsx +21 -29
  302. package/src/blocks/plan-card/plan-card.tsx +18 -16
  303. package/src/blocks/product-list-empty/product-list-empty.tsx +0 -5
  304. package/src/blocks/review-row/review-row.tsx +0 -10
  305. package/src/blocks/sales-chart/sales-chart.tsx +1 -6
  306. package/src/blocks/selection-bar/index.ts +1 -0
  307. package/src/blocks/selection-bar/selection-bar.tsx +63 -0
  308. package/src/blocks/service-state-banner/service-state-banner.tsx +17 -6
  309. package/src/blocks/shipping-tracking-row/shipping-tracking-row.tsx +0 -1
  310. package/src/blocks/site-preview-frame/site-preview-frame.tsx +20 -5
  311. package/src/blocks/stat-card/stat-card.tsx +1 -6
  312. package/src/blocks/step-screen/step-screen.tsx +0 -6
  313. package/src/blocks/supply-item-card/supply-item-card.tsx +0 -6
  314. package/src/charts/line-chart.tsx +11 -6
  315. package/src/charts/scale.ts +0 -3
  316. package/src/charts/sparkline.tsx +0 -4
  317. package/src/charts/summary.ts +0 -1
  318. package/src/components/button/button.tsx +3 -6
  319. package/src/components/chip/chip.tsx +17 -0
  320. package/src/components/chip-group/chip-group.tsx +2 -2
  321. package/src/components/dialog/dialog.tsx +3 -10
  322. package/src/components/divider/divider.tsx +0 -2
  323. package/src/components/empty-state/empty-state.tsx +0 -11
  324. package/src/components/field/field.tsx +59 -9
  325. package/src/components/list-row/list-row.tsx +0 -3
  326. package/src/components/photo/photo.tsx +0 -5
  327. package/src/components/price/price.tsx +1 -4
  328. package/src/components/progress-bar/index.ts +1 -0
  329. package/src/components/progress-bar/progress-bar.tsx +80 -0
  330. package/src/components/search-field/search-field.tsx +0 -1
  331. package/src/components/segmented-tabs/segmented-tabs.tsx +0 -1
  332. package/src/components/sheet/sheet.tsx +0 -3
  333. package/src/components/skeleton/skeleton.tsx +0 -4
  334. package/src/components/status-badge/status-badge.tsx +2 -3
  335. package/src/components/switch/switch.tsx +5 -3
  336. package/src/components/text/text.tsx +2 -5
  337. package/src/components/toast/toast.tsx +2 -13
  338. package/src/components/wizard-steps/wizard-steps.tsx +0 -3
  339. package/src/index.tsx +1 -0
  340. package/src/internal/glyphs.tsx +0 -3
  341. package/src/internal/icon.tsx +0 -1
  342. package/src/internal/overlay.tsx +0 -4
  343. package/src/internal/pressable-base.tsx +0 -3
  344. package/src/internal/use-reduced-motion.ts +0 -2
  345. package/src/sortable/move.ts +0 -1
  346. package/src/sortable/sortable-grid.tsx +0 -12
  347. package/src/sortable/sortable-list.tsx +0 -1
  348. package/src/theme/base.ts +113 -0
  349. package/src/theme/create-theme.ts +0 -5
  350. package/src/theme/theme-provider.tsx +0 -3
  351. package/src/theme/tokens.ts +20 -83
  352. package/src/types/index.ts +2 -9
  353. package/src/utils/color.ts +0 -3
  354. package/src/utils/styles.ts +0 -5
@@ -15,7 +15,6 @@ export type BrandProfileCardProps = {
15
15
  industry: string;
16
16
  tagline?: string;
17
17
  logo?: ImageSourcePropType;
18
- /** 브랜드 색 (hex) */
19
18
  colors?: readonly string[];
20
19
  keywords?: readonly string[];
21
20
  onEdit?: () => void;
@@ -36,7 +35,6 @@ const useStyles = makeStyles((t) => ({
36
35
  },
37
36
  }));
38
37
 
39
- /** AI가 만든 브랜드 요약 */
40
38
  export function BrandProfileCard({
41
39
  name,
42
40
  industry,
@@ -0,0 +1,187 @@
1
+ import { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';
2
+ import { ChipGroup } from '../../components/chip-group/chip-group';
3
+ import { Field } from '../../components/field/field';
4
+ import { Text } from '../../components/text/text';
5
+ import type { IconRenderProps } from '../../internal/icon';
6
+ import { PressableBase } from '../../internal/pressable-base';
7
+ import { useTheme } from '../../theme/theme-provider';
8
+ import { makeStyles } from '../../utils/styles';
9
+
10
+ export type ShipCarrier = { code: string; name: string };
11
+
12
+ export type BulkShipRow = {
13
+ id: string;
14
+ title: string;
15
+ subtitle?: string;
16
+ trackingNo: string;
17
+ };
18
+
19
+ export type BulkShipListProps = {
20
+ carriers: readonly ShipCarrier[];
21
+ carrier: string | null;
22
+ onCarrierChange: (code: string) => void;
23
+ rows: readonly BulkShipRow[];
24
+ onTrackingChange: (id: string, value: string) => void;
25
+ onScan?: (id: string) => void;
26
+ style?: StyleProp<ViewStyle>;
27
+ };
28
+
29
+ export type TrackingIssue = 'invalid' | 'duplicate';
30
+
31
+ const TRACKING = /^[0-9-]{8,20}$/;
32
+ const INVALID = '숫자와 -만 8~20자리로 입력해 주세요';
33
+ const DUPLICATE = '같은 송장 번호가 다른 주문에도 있어요';
34
+ const FIELD_HEIGHT = 52;
35
+
36
+ export function trackingIssues(
37
+ rows: readonly BulkShipRow[]
38
+ ): Record<string, TrackingIssue> {
39
+ const key = (v: string) => v.trim().replace(/-/g, '');
40
+ const seen = new Map<string, number>();
41
+ for (const row of rows) {
42
+ const k = key(row.trackingNo);
43
+ if (k && TRACKING.test(row.trackingNo.trim())) {
44
+ seen.set(k, (seen.get(k) ?? 0) + 1);
45
+ }
46
+ }
47
+ const issues: Record<string, TrackingIssue> = {};
48
+ for (const row of rows) {
49
+ const value = row.trackingNo.trim();
50
+ if (!value) continue;
51
+ if (!TRACKING.test(value)) issues[row.id] = 'invalid';
52
+ else if ((seen.get(key(value)) ?? 0) > 1) issues[row.id] = 'duplicate';
53
+ }
54
+ return issues;
55
+ }
56
+
57
+ const useStyles = makeStyles((t) => ({
58
+ root: { gap: t.space[5] },
59
+ carrier: { gap: t.space[2] },
60
+ list: { gap: t.space[4] },
61
+ row: { gap: t.space[2] },
62
+ input: { flexDirection: 'row', alignItems: 'flex-start', gap: t.space[2] },
63
+ field: { flex: 1 },
64
+ scan: {
65
+ width: FIELD_HEIGHT,
66
+ height: FIELD_HEIGHT,
67
+ alignItems: 'center',
68
+ justifyContent: 'center',
69
+ borderRadius: 10,
70
+ borderWidth: 1,
71
+ borderColor: t.colors.input,
72
+ backgroundColor: t.colors.background,
73
+ },
74
+ pressed: { backgroundColor: t.colors.muted },
75
+ }));
76
+
77
+ const g = StyleSheet.create({ absolute: { position: 'absolute' } });
78
+
79
+ function ScanGlyph({ color, size }: IconRenderProps) {
80
+ const stroke = Math.max(1.5, size / 12);
81
+ const arm = size * 0.3;
82
+ const corner = (v: 'top' | 'bottom', h: 'left' | 'right') => ({
83
+ position: 'absolute' as const,
84
+ width: arm,
85
+ height: arm,
86
+ borderColor: color,
87
+ [v]: 0,
88
+ [h]: 0,
89
+ [v === 'top' ? 'borderTopWidth' : 'borderBottomWidth']: stroke,
90
+ [h === 'left' ? 'borderLeftWidth' : 'borderRightWidth']: stroke,
91
+ });
92
+ return (
93
+ <View style={{ width: size, height: size }}>
94
+ <View style={corner('top', 'left')} />
95
+ <View style={corner('top', 'right')} />
96
+ <View style={corner('bottom', 'left')} />
97
+ <View style={corner('bottom', 'right')} />
98
+ <View
99
+ style={[
100
+ g.absolute,
101
+ {
102
+ left: size * 0.12,
103
+ right: size * 0.12,
104
+ top: (size - stroke) / 2,
105
+ height: stroke,
106
+ borderRadius: stroke,
107
+ backgroundColor: color,
108
+ },
109
+ ]}
110
+ />
111
+ </View>
112
+ );
113
+ }
114
+
115
+ export function BulkShipList({
116
+ carriers,
117
+ carrier,
118
+ onCarrierChange,
119
+ rows,
120
+ onTrackingChange,
121
+ onScan,
122
+ style,
123
+ }: BulkShipListProps) {
124
+ const t = useTheme();
125
+ const s = useStyles();
126
+ const issues = trackingIssues(rows);
127
+ return (
128
+ <View style={[s.root, style]}>
129
+ <View style={s.carrier}>
130
+ <Text weight="semibold" accessibilityRole="header">
131
+ 택배사
132
+ </Text>
133
+ <ChipGroup
134
+ items={carriers.map((c) => ({ value: c.code, label: c.name }))}
135
+ value={carrier}
136
+ onValueChange={(code) => {
137
+ if (code !== null) onCarrierChange(code);
138
+ }}
139
+ />
140
+ </View>
141
+ <View style={s.list}>
142
+ {rows.map((row) => {
143
+ const issue = issues[row.id];
144
+ return (
145
+ <View key={row.id} style={s.row}>
146
+ <View>
147
+ <Text weight="semibold" numberOfLines={1}>
148
+ {row.title}
149
+ </Text>
150
+ {row.subtitle ? (
151
+ <Text variant="caption" tone="muted" numberOfLines={1}>
152
+ {row.subtitle}
153
+ </Text>
154
+ ) : null}
155
+ </View>
156
+ <View style={s.input}>
157
+ <Field
158
+ style={s.field}
159
+ value={row.trackingNo}
160
+ onChangeText={(v) => onTrackingChange(row.id, v)}
161
+ placeholder="송장 번호"
162
+ keyboardType="number-pad"
163
+ inputMode="numeric"
164
+ autoCorrect={false}
165
+ maxLength={20}
166
+ accessibilityLabel={`${row.title} 송장 번호`}
167
+ error={issue === 'invalid' ? INVALID : undefined}
168
+ warning={issue === 'duplicate' ? DUPLICATE : undefined}
169
+ />
170
+ {onScan ? (
171
+ <PressableBase
172
+ accessibilityLabel={`${row.title} 송장 스캔`}
173
+ onPress={() => onScan(row.id)}
174
+ pressedStyle={s.pressed}
175
+ style={s.scan}
176
+ >
177
+ <ScanGlyph color={t.colors.foreground} size={22} />
178
+ </PressableBase>
179
+ ) : null}
180
+ </View>
181
+ </View>
182
+ );
183
+ })}
184
+ </View>
185
+ </View>
186
+ );
187
+ }
@@ -0,0 +1,8 @@
1
+ export {
2
+ BulkShipList,
3
+ trackingIssues,
4
+ type BulkShipListProps,
5
+ type BulkShipRow,
6
+ type ShipCarrier,
7
+ type TrackingIssue,
8
+ } from './bulk-ship-list';
@@ -1,27 +1,25 @@
1
1
  import { View, type StyleProp, type ViewStyle } from 'react-native';
2
- import { Button } from '../../components/button/button';
3
2
  import { formatPrice } from '../../components/price/price';
4
3
  import { Text } from '../../components/text/text';
5
4
  import { makeStyles } from '../../utils/styles';
6
5
  import { Card } from '../internal/card';
7
- import { formatDeadline } from '../internal/format';
8
6
 
9
7
  export type ClaimType = 'cancel' | 'return' | 'exchange';
10
- export type ClaimStatus = 'requested' | 'collecting' | 'completed' | 'rejected';
8
+ export type ClaimStatus =
9
+ | 'requested'
10
+ | 'collecting'
11
+ | 'collected'
12
+ | 'held'
13
+ | 'completed'
14
+ | 'rejected'
15
+ | 'withdrawn';
11
16
 
12
17
  export type ClaimRowProps = {
13
18
  type: ClaimType;
14
- /** 기본 'requested' */
15
19
  status?: ClaimStatus;
16
- /** 요청 금액 */
17
20
  amount: number;
18
- /** 예) '상품 파손' */
19
- reason: string;
20
- /** 처리 기한까지 남은 영업일. 임박했을 때만 표시한다 */
21
- dueInDays?: number;
22
- /** 요청 상태일 때 [거부] [승인] 버튼 */
23
- onReject?: () => void;
24
- onApprove?: () => void;
21
+ reason?: string;
22
+ dueAt?: Date | string;
25
23
  onPress?: () => void;
26
24
  style?: StyleProp<ViewStyle>;
27
25
  };
@@ -31,45 +29,73 @@ const TYPE: Record<ClaimType, string> = {
31
29
  return: '반품',
32
30
  exchange: '교환',
33
31
  };
34
- const STATUS: Record<ClaimStatus, string> = {
32
+
33
+ export const claimStatusLabel: Record<ClaimStatus, string> = {
35
34
  requested: '요청',
36
35
  collecting: '회수 중',
36
+ collected: '회수 완료',
37
+ held: '보류',
37
38
  completed: '완료',
38
- rejected: '거부',
39
+ rejected: '거절',
40
+ withdrawn: '철회',
39
41
  };
40
42
 
43
+ const OPEN: readonly ClaimStatus[] = [
44
+ 'requested',
45
+ 'collecting',
46
+ 'collected',
47
+ 'held',
48
+ ];
49
+
50
+ const DAY = 86400000;
51
+
52
+ function toDate(value: Date | string): Date {
53
+ if (typeof value !== 'string') return value;
54
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
55
+ return m
56
+ ? new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]))
57
+ : new Date(value);
58
+ }
59
+
60
+ function daysUntil(value: Date | string, now = new Date()): number | null {
61
+ const due = toDate(value);
62
+ if (Number.isNaN(due.getTime())) return null;
63
+ const a = new Date(now.getFullYear(), now.getMonth(), now.getDate());
64
+ const b = new Date(due.getFullYear(), due.getMonth(), due.getDate());
65
+ return Math.round((b.getTime() - a.getTime()) / DAY);
66
+ }
67
+
68
+ function formatDday(days: number): string {
69
+ if (days < 0) return '기한 지남';
70
+ return days === 0 ? 'D-day' : `D-${days}`;
71
+ }
72
+
41
73
  const useStyles = makeStyles((t) => ({
42
74
  row: { flexDirection: 'row', alignItems: 'center', gap: t.space[2] },
43
75
  grow: { flex: 1 },
44
76
  head: { fontSize: 16, lineHeight: 24, fontVariant: ['tabular-nums'] },
45
- deadline: { fontSize: 14, lineHeight: 20 },
46
- action: { flex: 1 },
77
+ deadline: { fontSize: 14, lineHeight: 20, fontVariant: ['tabular-nums'] },
47
78
  }));
48
79
 
49
- /** 취소 · 반품 · 교환 요청 한 건 */
50
80
  export function ClaimRow({
51
81
  type,
52
82
  status = 'requested',
53
83
  amount,
54
84
  reason,
55
- dueInDays,
56
- onReject,
57
- onApprove,
85
+ dueAt,
58
86
  onPress,
59
87
  style,
60
88
  }: ClaimRowProps) {
61
89
  const s = useStyles();
62
- const title = `${TYPE[type]} ${STATUS[status]}`;
63
- const open = status === 'requested' || status === 'collecting';
64
- const deadline =
65
- open && dueInDays !== undefined ? formatDeadline(dueInDays) : null;
66
- const actionable = status === 'requested' && (onReject || onApprove);
90
+ const title = `${TYPE[type]} ${claimStatusLabel[status]}`;
91
+ const days =
92
+ OPEN.includes(status) && dueAt !== undefined ? daysUntil(dueAt) : null;
93
+ const deadline = days === null ? null : formatDday(days);
94
+ const label = [title, formatPrice(amount), reason, deadline]
95
+ .filter(Boolean)
96
+ .join(', ');
67
97
  return (
68
- <Card
69
- onPress={onPress}
70
- accessibilityLabel={`${title}, ${formatPrice(amount)}, ${reason}${deadline ? `, ${deadline}` : ''}`}
71
- style={style}
72
- >
98
+ <Card onPress={onPress} accessibilityLabel={label} style={style}>
73
99
  <View style={s.row}>
74
100
  <Text weight="bold" style={[s.head, s.grow]} numberOfLines={1}>
75
101
  {title}
@@ -78,32 +104,19 @@ export function ClaimRow({
78
104
  {formatPrice(amount)}
79
105
  </Text>
80
106
  </View>
81
- <View style={s.row}>
82
- <Text style={s.grow} numberOfLines={1}>
83
- {reason}
84
- </Text>
85
- {deadline ? (
86
- <Text weight="bold" tone="destructive" style={s.deadline}>
87
- {deadline}
88
- </Text>
89
- ) : null}
90
- </View>
91
- {actionable ? (
107
+ {reason || deadline ? (
92
108
  <View style={s.row}>
93
- {onReject ? (
94
- <Button
95
- size="sm"
96
- variant="outline"
97
- style={s.action}
98
- onPress={onReject}
109
+ <Text style={s.grow} numberOfLines={1}>
110
+ {reason ?? ''}
111
+ </Text>
112
+ {deadline ? (
113
+ <Text
114
+ weight="bold"
115
+ tone={days !== null && days <= 1 ? 'danger' : 'muted'}
116
+ style={s.deadline}
99
117
  >
100
- 거부
101
- </Button>
102
- ) : null}
103
- {onApprove ? (
104
- <Button size="sm" style={s.action} onPress={onApprove}>
105
- 승인
106
- </Button>
118
+ {deadline}
119
+ </Text>
107
120
  ) : null}
108
121
  </View>
109
122
  ) : null}
@@ -1,5 +1,6 @@
1
1
  export {
2
2
  ClaimRow,
3
+ claimStatusLabel,
3
4
  type ClaimRowProps,
4
5
  type ClaimStatus,
5
6
  type ClaimType,
@@ -12,7 +12,6 @@ export type ColorSwatchPickerProps = {
12
12
  colors: readonly ColorSwatch[];
13
13
  value: string;
14
14
  onValueChange: (value: string) => void;
15
- /** 'circle'은 색 점, 'card'는 버튼 모양 미리보기. 기본 'circle' */
16
15
  variant?: 'circle' | 'card';
17
16
  style?: StyleProp<ViewStyle>;
18
17
  };
@@ -60,7 +59,6 @@ const useStyles = makeStyles((t) => ({
60
59
  short: { width: '45%' },
61
60
  }));
62
61
 
63
- /** 브랜드 색 고르기 */
64
62
  export function ColorSwatchPicker({
65
63
  colors,
66
64
  value,
@@ -8,14 +8,11 @@ import { makeStyles } from '../../utils/styles';
8
8
  export type CopyVariant = { id: string; text: string; locked?: boolean };
9
9
 
10
10
  export type CopyVariantPickerProps = {
11
- /** 예) '한 줄 소개' */
12
11
  label: string;
13
12
  variants: readonly CopyVariant[];
14
13
  selectedId: string | null;
15
14
  onSelect: (id: string) => void;
16
- /** 잠그면 다시 만들어도 이 문구는 바뀌지 않는다 */
17
15
  onToggleLock?: (id: string) => void;
18
- /** 다른 기기에서 먼저 수정했을 때(409) */
19
16
  conflict?: boolean;
20
17
  onReload?: () => void;
21
18
  style?: StyleProp<ViewStyle>;
@@ -66,7 +63,6 @@ const useStyles = makeStyles((t) => ({
66
63
  },
67
64
  }));
68
65
 
69
- /** AI가 만든 문구 후보 중 하나 고르기 */
70
66
  export function CopyVariantPicker({
71
67
  label,
72
68
  variants,
@@ -84,7 +80,7 @@ export function CopyVariantPicker({
84
80
  <Text weight="semibold">{label}</Text>
85
81
  {conflict ? (
86
82
  <View style={s.conflict} accessibilityLiveRegion="polite">
87
- <Text tone="destructive">다른 기기에서 먼저 수정했어요.</Text>
83
+ <Text tone="danger">다른 기기에서 먼저 수정했어요.</Text>
88
84
  {onReload ? (
89
85
  <Button
90
86
  size="sm"
@@ -7,10 +7,9 @@ import { Card } from '../internal/card';
7
7
 
8
8
  export type CreditWalletProps = {
9
9
  balance: number;
10
- /** 이번 달에 사라지는 크레딧. 0보다 크면 보여준다 */
11
10
  expiring?: number;
12
11
  todayUsed: number;
13
- dailyLimit: number;
12
+ dailyLimit: number | null;
14
13
  onBuy?: () => void;
15
14
  onHistory?: () => void;
16
15
  style?: StyleProp<ViewStyle>;
@@ -43,7 +42,6 @@ const useStyles = makeStyles((t) => ({
43
42
  action: { flex: 1 },
44
43
  }));
45
44
 
46
- /** 보유 크레딧과 오늘 생성 횟수 */
47
45
  export function CreditWallet({
48
46
  balance,
49
47
  expiring,
@@ -54,7 +52,12 @@ export function CreditWallet({
54
52
  style,
55
53
  }: CreditWalletProps) {
56
54
  const s = useStyles();
57
- const ratio = dailyLimit > 0 ? Math.min(1, todayUsed / dailyLimit) : 1;
55
+ const ratio =
56
+ dailyLimit === null
57
+ ? 0
58
+ : dailyLimit > 0
59
+ ? Math.min(1, todayUsed / dailyLimit)
60
+ : 1;
58
61
  return (
59
62
  <View style={[s.root, style]}>
60
63
  <Card>
@@ -87,18 +90,21 @@ export function CreditWallet({
87
90
  <View style={s.row}>
88
91
  <Text weight="semibold">오늘 생성</Text>
89
92
  <Text>
90
- <Text weight="bold">{todayUsed}</Text> / {dailyLimit}
93
+ <Text weight="bold">{todayUsed}</Text> /{' '}
94
+ {dailyLimit === null ? '무제한' : dailyLimit}
91
95
  </Text>
92
96
  </View>
93
- <View
94
- accessible
95
- accessibilityRole="progressbar"
96
- accessibilityLabel="오늘 생성"
97
- accessibilityValue={{ min: 0, max: dailyLimit, now: todayUsed }}
98
- style={s.meter}
99
- >
100
- <View style={[s.fill, { width: `${ratio * 100}%` }]} />
101
- </View>
97
+ {dailyLimit === null ? null : (
98
+ <View
99
+ accessible
100
+ accessibilityRole="progressbar"
101
+ accessibilityLabel="오늘 생성"
102
+ accessibilityValue={{ min: 0, max: dailyLimit, now: todayUsed }}
103
+ style={s.meter}
104
+ >
105
+ <View style={[s.fill, { width: `${ratio * 100}%` }]} />
106
+ </View>
107
+ )}
102
108
  </Card>
103
109
  </View>
104
110
  );
@@ -0,0 +1,180 @@
1
+ import {
2
+ ActivityIndicator,
3
+ View,
4
+ type StyleProp,
5
+ type ViewStyle,
6
+ } from 'react-native';
7
+ import { Button } from '../../components/button/button';
8
+ import { Text } from '../../components/text/text';
9
+ import { AlertGlyph, CheckGlyph } from '../../internal/glyphs';
10
+ import { useTheme } from '../../theme/theme-provider';
11
+ import { makeStyles } from '../../utils/styles';
12
+ import { Card } from '../internal/card';
13
+
14
+ export type GenerationStatus = 'queued' | 'running' | 'done' | 'failed';
15
+
16
+ export type GenerationStep = { key: string; label: string };
17
+
18
+ export type GenerationProgressProps = {
19
+ steps: readonly GenerationStep[];
20
+ current: string | null;
21
+ status: GenerationStatus;
22
+ errorText?: string;
23
+ onRetry?: () => void;
24
+ creditNote?: string;
25
+ style?: StyleProp<ViewStyle>;
26
+ };
27
+
28
+ type StepState = 'done' | 'active' | 'waiting' | 'pending' | 'failed';
29
+
30
+ const HEADLINE: Record<GenerationStatus, string> = {
31
+ queued: '접수했어요. 곧 시작해요',
32
+ running: '만들고 있어요',
33
+ done: '다 만들었어요',
34
+ failed: '만들지 못했어요',
35
+ };
36
+
37
+ const STATE_LABEL: Record<StepState, string> = {
38
+ done: '완료',
39
+ active: '진행 중',
40
+ waiting: '대기 중',
41
+ pending: '대기',
42
+ failed: '실패',
43
+ };
44
+
45
+ const DOT = 24;
46
+
47
+ const useStyles = makeStyles((t) => ({
48
+ list: { gap: t.space[3] },
49
+ row: { flexDirection: 'row', alignItems: 'center', gap: t.space[3] },
50
+ label: { flex: 1 },
51
+ dot: {
52
+ width: DOT,
53
+ height: DOT,
54
+ borderRadius: DOT / 2,
55
+ alignItems: 'center',
56
+ justifyContent: 'center',
57
+ },
58
+ doneDot: { backgroundColor: t.colors.primary },
59
+ pendingDot: { borderWidth: 2, borderColor: t.colors.input },
60
+ waitingDot: { borderWidth: 2, borderColor: t.colors.primary },
61
+ start: { alignSelf: 'flex-start' },
62
+ }));
63
+
64
+ function stepState(
65
+ index: number,
66
+ currentIndex: number,
67
+ status: GenerationStatus
68
+ ): StepState {
69
+ if (status === 'done') return 'done';
70
+ if (currentIndex < 0) return 'pending';
71
+ if (index < currentIndex) return 'done';
72
+ if (index > currentIndex) return 'pending';
73
+ if (status === 'failed') return 'failed';
74
+ return status === 'running' ? 'active' : 'waiting';
75
+ }
76
+
77
+ export function GenerationProgress({
78
+ steps,
79
+ current,
80
+ status,
81
+ errorText,
82
+ onRetry,
83
+ creditNote,
84
+ style,
85
+ }: GenerationProgressProps) {
86
+ const t = useTheme();
87
+ const s = useStyles();
88
+ const currentIndex =
89
+ current === null ? -1 : steps.findIndex((step) => step.key === current);
90
+ const indicator = (state: StepState) => {
91
+ switch (state) {
92
+ case 'done':
93
+ return (
94
+ <View style={[s.dot, s.doneDot]}>
95
+ <CheckGlyph color={t.colors.primaryForeground} size={14} />
96
+ </View>
97
+ );
98
+ case 'active':
99
+ return (
100
+ <View style={s.dot}>
101
+ <ActivityIndicator size="small" color={t.colors.primary} />
102
+ </View>
103
+ );
104
+ case 'failed':
105
+ return (
106
+ <View style={s.dot}>
107
+ <AlertGlyph
108
+ filled
109
+ color={t.colors.danger}
110
+ onColor={t.colors.dangerForeground}
111
+ size={DOT}
112
+ />
113
+ </View>
114
+ );
115
+ case 'waiting':
116
+ return <View style={[s.dot, s.waitingDot]} />;
117
+ default:
118
+ return <View style={[s.dot, s.pendingDot]} />;
119
+ }
120
+ };
121
+ return (
122
+ <Card style={style}>
123
+ <Text
124
+ variant="bodyLg"
125
+ weight="bold"
126
+ accessibilityRole="header"
127
+ accessibilityLiveRegion="polite"
128
+ >
129
+ {HEADLINE[status]}
130
+ </Text>
131
+ <View style={s.list}>
132
+ {steps.map((step, i) => {
133
+ const state = stepState(i, currentIndex, status);
134
+ return (
135
+ <View
136
+ key={step.key}
137
+ accessible
138
+ accessibilityLabel={`${step.label}, ${STATE_LABEL[state]}`}
139
+ style={s.row}
140
+ >
141
+ {indicator(state)}
142
+ <Text
143
+ style={s.label}
144
+ tone={
145
+ state === 'failed'
146
+ ? 'danger'
147
+ : state === 'pending'
148
+ ? 'muted'
149
+ : 'default'
150
+ }
151
+ weight={
152
+ state === 'active' || state === 'failed'
153
+ ? 'semibold'
154
+ : undefined
155
+ }
156
+ >
157
+ {step.label}
158
+ </Text>
159
+ </View>
160
+ );
161
+ })}
162
+ </View>
163
+ {status === 'failed' && errorText ? (
164
+ <Text tone="danger" accessibilityLiveRegion="polite">
165
+ {errorText}
166
+ </Text>
167
+ ) : null}
168
+ {status === 'failed' && onRetry ? (
169
+ <Button variant="outline" onPress={onRetry} style={s.start}>
170
+ 다시 시도
171
+ </Button>
172
+ ) : null}
173
+ {creditNote ? (
174
+ <Text variant="caption" tone="muted">
175
+ {creditNote}
176
+ </Text>
177
+ ) : null}
178
+ </Card>
179
+ );
180
+ }
@@ -0,0 +1,6 @@
1
+ export {
2
+ GenerationProgress,
3
+ type GenerationProgressProps,
4
+ type GenerationStatus,
5
+ type GenerationStep,
6
+ } from './generation-progress';