@zerodev/react-ui 0.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.
- package/README.md +89 -0
- package/dist/_types/components/Badge/index.d.ts +10 -0
- package/dist/_types/components/Badge/index.d.ts.map +1 -0
- package/dist/_types/components/Button/index.d.ts +10 -0
- package/dist/_types/components/Button/index.d.ts.map +1 -0
- package/dist/_types/components/Callout/index.d.ts +6 -0
- package/dist/_types/components/Callout/index.d.ts.map +1 -0
- package/dist/_types/components/Icon/index.d.ts +9 -0
- package/dist/_types/components/Icon/index.d.ts.map +1 -0
- package/dist/_types/components/IconButton/index.d.ts +7 -0
- package/dist/_types/components/IconButton/index.d.ts.map +1 -0
- package/dist/_types/components/Input/index.d.ts +13 -0
- package/dist/_types/components/Input/index.d.ts.map +1 -0
- package/dist/_types/components/ListItem/index.d.ts +23 -0
- package/dist/_types/components/ListItem/index.d.ts.map +1 -0
- package/dist/_types/components/Switch/index.d.ts +6 -0
- package/dist/_types/components/Switch/index.d.ts.map +1 -0
- package/dist/_types/components/Text/index.d.ts +8 -0
- package/dist/_types/components/Text/index.d.ts.map +1 -0
- package/dist/_types/components/WrappedPressable/index.d.ts +7 -0
- package/dist/_types/components/WrappedPressable/index.d.ts.map +1 -0
- package/dist/_types/components/Wrapper/index.d.ts +7 -0
- package/dist/_types/components/Wrapper/index.d.ts.map +1 -0
- package/dist/_types/index.d.ts +17 -0
- package/dist/_types/index.d.ts.map +1 -0
- package/dist/_types/utils/common.d.ts +3 -0
- package/dist/_types/utils/common.d.ts.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +3751 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +2 -0
- package/package.json +84 -0
- package/src/components/Badge/index.tsx +45 -0
- package/src/components/Button/index.tsx +81 -0
- package/src/components/Callout/index.tsx +23 -0
- package/src/components/Icon/index.tsx +43 -0
- package/src/components/IconButton/index.tsx +24 -0
- package/src/components/Input/index.tsx +147 -0
- package/src/components/ListItem/index.tsx +136 -0
- package/src/components/Switch/index.tsx +35 -0
- package/src/components/Text/index.tsx +20 -0
- package/src/components/WrappedPressable/index.tsx +46 -0
- package/src/components/Wrapper/index.tsx +43 -0
- package/src/index.ts +33 -0
- package/src/svg.d.ts +6 -0
- package/src/utils/common.ts +17 -0
- package/tailwind.config.ts +58 -0
package/dist/styles.css
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--zd-font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--zd-color-gray-700:oklch(37.3% .034 259.733);--zd-color-gray-900:oklch(21% .034 264.665);--zd-color-white:#fff;--zd-spacing:.25rem;--zd-text-sm--line-height:calc(1.25 / .875);--zd-text-base--line-height:calc(1.5 / 1);--zd-text-lg--line-height:calc(1.75 / 1.125);--zd-text-2xl--line-height:calc(2 / 1.5);--zd-font-weight-medium:500;--zd-font-weight-semibold:600;--zd-font-weight-bold:700;--zd-radius-lg:.5rem;--zd-radius-xl:.75rem;--zd-radius-2xl:1rem;--zd-radius-3xl:1.5rem;--zd-animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--zd-default-transition-duration:.15s;--zd-default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--zd-default-font-family:sans-serif;--zd-default-mono-font-family:var(--zd-font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--zd-default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--zd-default-font-feature-settings,normal);font-variation-settings:var(--zd-default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--zd-default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--zd-default-mono-font-feature-settings,normal);font-variation-settings:var(--zd-default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.zd\:pointer-events-none{pointer-events:none}.zd\:absolute{position:absolute}.zd\:relative{position:relative}.zd\:inset-0{inset:calc(var(--zd-spacing) * 0)}.zd\:mb-2{margin-bottom:calc(var(--zd-spacing) * 2)}.zd\:flex{display:flex}.zd\:grid{display:grid}.zd\:h-2\.5{height:calc(var(--zd-spacing) * 2.5)}.zd\:h-3{height:calc(var(--zd-spacing) * 3)}.zd\:h-3\.5{height:calc(var(--zd-spacing) * 3.5)}.zd\:h-5{height:calc(var(--zd-spacing) * 5)}.zd\:h-6{height:calc(var(--zd-spacing) * 6)}.zd\:h-7{height:calc(var(--zd-spacing) * 7)}.zd\:h-11{height:calc(var(--zd-spacing) * 11)}.zd\:h-12{height:calc(var(--zd-spacing) * 12)}.zd\:h-13{height:52px}.zd\:h-16{height:calc(var(--zd-spacing) * 16)}.zd\:h-32{height:calc(var(--zd-spacing) * 32)}.zd\:h-\[52px\]{height:52px}.zd\:h-\[68px\]{height:68px}.zd\:h-full{height:100%}.zd\:min-h-11{min-height:calc(var(--zd-spacing) * 11)}.zd\:min-h-\[300px\]{min-height:300px}.zd\:w-2\.5{width:calc(var(--zd-spacing) * 2.5)}.zd\:w-3{width:calc(var(--zd-spacing) * 3)}.zd\:w-3\.5{width:calc(var(--zd-spacing) * 3.5)}.zd\:w-5{width:calc(var(--zd-spacing) * 5)}.zd\:w-6{width:calc(var(--zd-spacing) * 6)}.zd\:w-13{width:52px}.zd\:w-14{width:calc(var(--zd-spacing) * 14)}.zd\:w-72{width:calc(var(--zd-spacing) * 72)}.zd\:w-80{width:calc(var(--zd-spacing) * 80)}.zd\:w-\[52px\]{width:52px}.zd\:w-full{width:100%}.zd\:min-w-0{min-width:calc(var(--zd-spacing) * 0)}.zd\:min-w-\[400px\]{min-width:400px}.zd\:flex-1{flex:1}.zd\:shrink-0{flex-shrink:0}.zd\:animate-pulse{animation:var(--zd-animate-pulse)}.zd\:cursor-not-allowed{cursor:not-allowed}.zd\:cursor-pointer{cursor:pointer}.zd\:resize-none{resize:none}.zd\:flex-col{flex-direction:column}.zd\:flex-row{flex-direction:row}.zd\:flex-wrap{flex-wrap:wrap}.zd\:place-items-center{place-items:center}.zd\:items-center{align-items:center}.zd\:justify-between{justify-content:space-between}.zd\:justify-center{justify-content:center}.zd\:gap-1{gap:calc(var(--zd-spacing) * 1)}.zd\:gap-1\.5{gap:calc(var(--zd-spacing) * 1.5)}.zd\:gap-2{gap:calc(var(--zd-spacing) * 2)}.zd\:gap-3{gap:calc(var(--zd-spacing) * 3)}.zd\:gap-4{gap:calc(var(--zd-spacing) * 4)}.zd\:self-end{align-self:flex-end}.zd\:self-start{align-self:flex-start}.zd\:overflow-hidden{overflow:hidden}.zd\:rounded-2xl{border-radius:var(--zd-radius-2xl)}.zd\:rounded-3xl{border-radius:var(--zd-radius-3xl)}.zd\:rounded-full{border-radius:3.40282e38px}.zd\:rounded-lg{border-radius:var(--zd-radius-lg)}.zd\:rounded-xl{border-radius:var(--zd-radius-xl)}.zd\:border-0{border-style:var(--tw-border-style);border-width:0}.zd\:border-\[0\.3px\]{border-style:var(--tw-border-style);border-width:.3px}.zd\:border-offWhite{border-color:#f7f5f0}.zd\:border-white\/0{border-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:border-white\/0{border-color:color-mix(in oklab, var(--zd-color-white) 0%, transparent)}}.zd\:bg-greyScale\/30{background-color:oklab(16.9052% .00636494 .00836386/.3)}.zd\:bg-offWhite\/50{background-color:oklab(97.0302% .000165075 .00696582/.5)}.zd\:bg-orange\/10{background-color:oklab(70.9342% .114827 .116983/.1)}.zd\:bg-solarOrange{background-color:#e76000}.zd\:bg-solarOrange\/15{background-color:oklab(65.138% .131584 .131685/.15)}.zd\:bg-transparent{background-color:#0000}.zd\:bg-white,.zd\:bg-white\/20{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:bg-white\/20{background-color:color-mix(in oklab, var(--zd-color-white) 20%, transparent)}}.zd\:bg-white\/40{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:bg-white\/40{background-color:color-mix(in oklab, var(--zd-color-white) 40%, transparent)}}.zd\:bg-white\/70{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:bg-white\/70{background-color:color-mix(in oklab, var(--zd-color-white) 70%, transparent)}}.zd\:p-1{padding:calc(var(--zd-spacing) * 1)}.zd\:p-2{padding:calc(var(--zd-spacing) * 2)}.zd\:p-4{padding:calc(var(--zd-spacing) * 4)}.zd\:p-6{padding:calc(var(--zd-spacing) * 6)}.zd\:px-0{padding-inline:calc(var(--zd-spacing) * 0)}.zd\:px-2{padding-inline:calc(var(--zd-spacing) * 2)}.zd\:px-4{padding-inline:calc(var(--zd-spacing) * 4)}.zd\:px-5{padding-inline:calc(var(--zd-spacing) * 5)}.zd\:px-6{padding-inline:calc(var(--zd-spacing) * 6)}.zd\:py-1{padding-block:calc(var(--zd-spacing) * 1)}.zd\:py-3{padding-block:calc(var(--zd-spacing) * 3)}.zd\:py-3\.5{padding-block:calc(var(--zd-spacing) * 3.5)}.zd\:py-5{padding-block:calc(var(--zd-spacing) * 5)}.zd\:pr-1{padding-right:calc(var(--zd-spacing) * 1)}.zd\:pr-2{padding-right:calc(var(--zd-spacing) * 2)}.zd\:pl-2{padding-left:calc(var(--zd-spacing) * 2)}.zd\:pl-4{padding-left:calc(var(--zd-spacing) * 4)}.zd\:text-left{text-align:left}.zd\:font-roboto{font-family:Roboto,sans-serif}.zd\:font-sans{font-family:sans-serif}.zd\:text-2xl{font-size:20px;line-height:var(--tw-leading,var(--zd-text-2xl--line-height))}.zd\:text-base{font-size:14px;line-height:var(--tw-leading,var(--zd-text-base--line-height))}.zd\:text-body1{font-size:16px;line-height:var(--tw-leading,130%)}.zd\:text-body2{font-size:14px;line-height:var(--tw-leading,130%)}.zd\:text-body3{font-size:12px;line-height:var(--tw-leading,130%)}.zd\:text-body4{font-size:10px;line-height:var(--tw-leading,130%)}.zd\:text-h1{font-size:42px;line-height:var(--tw-leading,110%)}.zd\:text-h2{font-size:28px;line-height:var(--tw-leading,110%)}.zd\:text-h3{font-size:18px;line-height:var(--tw-leading,130%)}.zd\:text-lg{font-size:16px;line-height:var(--tw-leading,var(--zd-text-lg--line-height))}.zd\:text-sm{font-size:12px;line-height:var(--tw-leading,var(--zd-text-sm--line-height))}.zd\:font-bold{--tw-font-weight:var(--zd-font-weight-bold);font-weight:var(--zd-font-weight-bold)}.zd\:font-medium{--tw-font-weight:var(--zd-font-weight-medium);font-weight:var(--zd-font-weight-medium)}.zd\:font-semibold{--tw-font-weight:var(--zd-font-weight-semibold);font-weight:var(--zd-font-weight-semibold)}.zd\:break-all{word-break:break-all}.zd\:text-gray-700{color:var(--zd-color-gray-700)}.zd\:text-gray-900{color:var(--zd-color-gray-900)}.zd\:text-greyScale{color:#130e0b}.zd\:text-greyScale\/50{color:oklab(16.9052% .00636494 .00836386/.5)}.zd\:text-greyScale\/90{color:oklab(16.9052% .00636494 .00836386/.9)}.zd\:text-orange{color:#f27b3e}.zd\:text-solarOrange{color:#e76000}.zd\:text-white{color:var(--zd-color-white)}.zd\:caret-gray-900{caret-color:var(--zd-color-gray-900)}.zd\:opacity-50{opacity:.5}.zd\:shadow-\[inset_0_-4px_4px_0_rgba\(255\,255\,255\,0\.10\)\,inset_0_3px_4px_0_rgba\(0\,0\,0\,0\.02\)\]{--tw-shadow:inset 0 -4px 4px 0 var(--tw-shadow-color,#ffffff1a), inset 0 3px 4px 0 var(--tw-shadow-color,#00000005);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.zd\:shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.zd\:backdrop-blur-\[15px\]{--tw-backdrop-blur:blur(15px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.zd\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--zd-default-transition-timing-function));transition-duration:var(--tw-duration,var(--zd-default-transition-duration))}.zd\:outline-none{--tw-outline-style:none;outline-style:none}.zd\:placeholder\:text-gray-900\/50::placeholder{color:var(--zd-color-gray-900)}@supports (color:color-mix(in lab, red, red)){.zd\:placeholder\:text-gray-900\/50::placeholder{color:color-mix(in oklab, var(--zd-color-gray-900) 50%, transparent)}}@media (hover:hover){.zd\:hover\:bg-white\/5:hover{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:hover\:bg-white\/5:hover{background-color:color-mix(in oklab, var(--zd-color-white) 5%, transparent)}}.zd\:hover\:bg-white\/20:hover{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:hover\:bg-white\/20:hover{background-color:color-mix(in oklab, var(--zd-color-white) 20%, transparent)}}}.zd\:active\:bg-white\/10:active{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:active\:bg-white\/10:active{background-color:color-mix(in oklab, var(--zd-color-white) 10%, transparent)}}.zd\:active\:bg-white\/30:active{background-color:var(--zd-color-white)}@supports (color:color-mix(in lab, red, red)){.zd\:active\:bg-white\/30:active{background-color:color-mix(in oklab, var(--zd-color-white) 30%, transparent)}}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}
|
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zerodev/react-ui",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "React UI primitives for ZeroDev",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/zerodevapp/zerodev-wallet-sdk.git",
|
|
8
|
+
"directory": "packages/react-ui"
|
|
9
|
+
},
|
|
10
|
+
"sideEffects": [
|
|
11
|
+
"**/*.css"
|
|
12
|
+
],
|
|
13
|
+
"main": "./dist/index.cjs",
|
|
14
|
+
"module": "./dist/index.mjs",
|
|
15
|
+
"types": "./dist/_types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/_types/index.d.ts",
|
|
19
|
+
"import": "./dist/index.mjs",
|
|
20
|
+
"require": "./dist/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./styles.css": "./dist/styles.css"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"tailwind.config.ts",
|
|
27
|
+
"src/**/*.ts",
|
|
28
|
+
"src/**/*.tsx",
|
|
29
|
+
"!dist/**/*.tsbuildinfo",
|
|
30
|
+
"!.env",
|
|
31
|
+
"!src/**/*.test.ts",
|
|
32
|
+
"!src/**/*.test.tsx",
|
|
33
|
+
"!src/**/*.stories.ts",
|
|
34
|
+
"!src/**/*.stories.tsx",
|
|
35
|
+
"!.changeset"
|
|
36
|
+
],
|
|
37
|
+
"keywords": [
|
|
38
|
+
"react",
|
|
39
|
+
"components",
|
|
40
|
+
"ui",
|
|
41
|
+
"primitives",
|
|
42
|
+
"zerodev"
|
|
43
|
+
],
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@storybook/addon-a11y": "^10.3.3",
|
|
49
|
+
"@storybook/addon-docs": "^10.3.3",
|
|
50
|
+
"@storybook/react-vite": "^10.3.3",
|
|
51
|
+
"@tailwindcss/cli": "^4.2.2",
|
|
52
|
+
"@tailwindcss/postcss": "^4.2.2",
|
|
53
|
+
"@testing-library/react": "^16.3.0",
|
|
54
|
+
"@types/react": "^19",
|
|
55
|
+
"@types/react-dom": "^19",
|
|
56
|
+
"@vitejs/plugin-react": "^4.7.0",
|
|
57
|
+
"postcss": "^8.5.10",
|
|
58
|
+
"react": "19.2.0",
|
|
59
|
+
"react-dom": "19.2.0",
|
|
60
|
+
"storybook": "^10.3.3",
|
|
61
|
+
"tailwindcss": "^4.2.2",
|
|
62
|
+
"typescript": "5.9.3",
|
|
63
|
+
"vite": "^6.4.1",
|
|
64
|
+
"vite-plugin-svgr": "5.0.0"
|
|
65
|
+
},
|
|
66
|
+
"dependencies": {
|
|
67
|
+
"clsx": "^2.1.1",
|
|
68
|
+
"tailwind-merge": "^3.5.0"
|
|
69
|
+
},
|
|
70
|
+
"scripts": {
|
|
71
|
+
"build": "pnpm run clean && pnpm run build:css && pnpm run build:js && pnpm run build:types",
|
|
72
|
+
"build:css": "npx @tailwindcss/cli -i ./src/styles.css -o ./dist/styles.css --minify",
|
|
73
|
+
"build:js": "vite build",
|
|
74
|
+
"build:types": "tsc --project ./tsconfig.build.json --outDir ./dist/_types --emitDeclarationOnly --declaration --declarationMap",
|
|
75
|
+
"dev": "tsc --watch",
|
|
76
|
+
"dev:css": "npx @tailwindcss/cli -i ./src/styles.css -o ./dist/styles.css --watch",
|
|
77
|
+
"typecheck": "tsc --noEmit --project ./tsconfig.build.json",
|
|
78
|
+
"clean": "rm -rf dist",
|
|
79
|
+
"storybook": "storybook dev -p 6006",
|
|
80
|
+
"build-storybook": "storybook build",
|
|
81
|
+
"test": "vitest run",
|
|
82
|
+
"test:watch": "vitest"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { cn } from '../../utils/common'
|
|
2
|
+
import { Icon, type IconName } from '../Icon'
|
|
3
|
+
import { Text } from '../Text'
|
|
4
|
+
|
|
5
|
+
export interface BadgeProps {
|
|
6
|
+
text: string
|
|
7
|
+
variant?: 'primary' | 'secondary'
|
|
8
|
+
leadingIcon?: IconName
|
|
9
|
+
trailingIcon?: IconName
|
|
10
|
+
className?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const variantStyles = {
|
|
14
|
+
primary: 'zd:bg-white/40',
|
|
15
|
+
secondary: 'zd:bg-orange/10',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function Badge({
|
|
19
|
+
text,
|
|
20
|
+
variant = 'primary',
|
|
21
|
+
leadingIcon,
|
|
22
|
+
trailingIcon,
|
|
23
|
+
className,
|
|
24
|
+
}: BadgeProps) {
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
className={cn(
|
|
28
|
+
'zd:py-1 zd:px-2 zd:gap-1 zd:flex zd:flex-row zd:items-center zd:rounded-lg zd:self-start',
|
|
29
|
+
variantStyles[variant],
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
>
|
|
33
|
+
{leadingIcon && (
|
|
34
|
+
<Icon
|
|
35
|
+
name={leadingIcon}
|
|
36
|
+
className="zd:w-3 zd:h-3 zd:text-solarOrange"
|
|
37
|
+
/>
|
|
38
|
+
)}
|
|
39
|
+
<Text className="zd:text-body3">{text}</Text>
|
|
40
|
+
{trailingIcon && (
|
|
41
|
+
<Icon name={trailingIcon} className="zd:w-2.5 zd:h-2.5" />
|
|
42
|
+
)}
|
|
43
|
+
</div>
|
|
44
|
+
)
|
|
45
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes, CSSProperties } from 'react'
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../utils/common'
|
|
4
|
+
import { Icon, type IconName } from '../Icon'
|
|
5
|
+
import { Text } from '../Text'
|
|
6
|
+
import { Wrapper } from '../Wrapper'
|
|
7
|
+
|
|
8
|
+
// The frosted surface (white@0.5 bg, 0.3px border, 15px blur) comes from Wrapper.
|
|
9
|
+
// Button layers on top of it the Figma button spec: 24px radius, a transparent
|
|
10
|
+
// border (overriding Wrapper's offWhite stroke), and the "blur effect" inset
|
|
11
|
+
// shadows. Per-variant colour + hover/active live on the inner <button>.
|
|
12
|
+
const surfaceClass =
|
|
13
|
+
'zd:rounded-3xl zd:border-white/0 ' +
|
|
14
|
+
'zd:shadow-[inset_0_-4px_4px_0_rgba(255,255,255,0.10),inset_0_3px_4px_0_rgba(0,0,0,0.02)]'
|
|
15
|
+
|
|
16
|
+
const innerClass =
|
|
17
|
+
'zd:flex zd:items-center zd:justify-center zd:gap-2 zd:h-16 zd:w-full zd:px-5 zd:py-3.5 zd:cursor-pointer zd:transition-colors'
|
|
18
|
+
|
|
19
|
+
// secondary keeps Wrapper's white@0.5 surface; primary overrides it with a dark
|
|
20
|
+
// translucent fill (via inline style, since Wrapper sets its bg inline). Hover/
|
|
21
|
+
// active tints sit on the inner button.
|
|
22
|
+
const bgClasses: Record<NonNullable<ButtonProps['action']>, string> = {
|
|
23
|
+
primary: 'zd:hover:bg-white/5 zd:active:bg-white/10',
|
|
24
|
+
secondary: 'zd:hover:bg-white/20 zd:active:bg-white/30',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const primaryStyle: CSSProperties = {
|
|
28
|
+
backgroundColor: 'rgba(19, 14, 11, 0.9)',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const textClasses: Record<NonNullable<ButtonProps['action']>, string> = {
|
|
32
|
+
primary: 'zd:text-white zd:text-body1',
|
|
33
|
+
secondary: 'zd:text-greyScale zd:text-body1',
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
37
|
+
text?: string
|
|
38
|
+
iconName?: IconName
|
|
39
|
+
action?: 'primary' | 'secondary'
|
|
40
|
+
trailIcon?: boolean
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function Button({
|
|
44
|
+
text,
|
|
45
|
+
className,
|
|
46
|
+
iconName,
|
|
47
|
+
trailIcon,
|
|
48
|
+
disabled,
|
|
49
|
+
action = 'primary',
|
|
50
|
+
...rest
|
|
51
|
+
}: ButtonProps) {
|
|
52
|
+
return (
|
|
53
|
+
<Wrapper
|
|
54
|
+
className={cn(surfaceClass, { 'zd:opacity-50': disabled }, className)}
|
|
55
|
+
{...(action === 'primary' && { style: primaryStyle })}
|
|
56
|
+
>
|
|
57
|
+
<button
|
|
58
|
+
type={rest.type ?? 'button'}
|
|
59
|
+
className={cn(innerClass, bgClasses[action], {
|
|
60
|
+
'zd:cursor-not-allowed': disabled,
|
|
61
|
+
})}
|
|
62
|
+
disabled={disabled}
|
|
63
|
+
{...rest}
|
|
64
|
+
>
|
|
65
|
+
{iconName && !trailIcon && (
|
|
66
|
+
<Icon
|
|
67
|
+
name={iconName}
|
|
68
|
+
className={cn('zd:w-6 zd:h-6', textClasses[action])}
|
|
69
|
+
/>
|
|
70
|
+
)}
|
|
71
|
+
{text && <Text className={textClasses[action]}>{text}</Text>}
|
|
72
|
+
{iconName && trailIcon && (
|
|
73
|
+
<Icon
|
|
74
|
+
name={iconName}
|
|
75
|
+
className={cn('zd:w-6 zd:h-6', textClasses[action])}
|
|
76
|
+
/>
|
|
77
|
+
)}
|
|
78
|
+
</button>
|
|
79
|
+
</Wrapper>
|
|
80
|
+
)
|
|
81
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Icon } from '../Icon'
|
|
2
|
+
import { Text } from '../Text'
|
|
3
|
+
import { Wrapper } from '../Wrapper'
|
|
4
|
+
|
|
5
|
+
export interface CalloutProps {
|
|
6
|
+
title: string
|
|
7
|
+
description: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Callout({ title, description }: CalloutProps) {
|
|
11
|
+
return (
|
|
12
|
+
<Wrapper
|
|
13
|
+
className="zd:w-full zd:py-5 zd:px-4 zd:flex zd:flex-col zd:gap-4 zd:rounded-xl"
|
|
14
|
+
variant="solid"
|
|
15
|
+
>
|
|
16
|
+
<div className="zd:flex zd:flex-row zd:items-center zd:gap-2">
|
|
17
|
+
<Icon name="info" className="zd:h-3.5 zd:w-3.5 zd:text-solarOrange" />
|
|
18
|
+
<Text className="zd:text-body1">{title}</Text>
|
|
19
|
+
</div>
|
|
20
|
+
<Text className="zd:text-body3 zd:break-all">{description}</Text>
|
|
21
|
+
</Wrapper>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { FC, SVGProps } from 'react'
|
|
2
|
+
import { cn } from '../../utils/common'
|
|
3
|
+
|
|
4
|
+
type SvgModule = { default: FC<SVGProps<SVGSVGElement>> }
|
|
5
|
+
|
|
6
|
+
// Eagerly import every .svg from assets/icons/ as a React component
|
|
7
|
+
const svgModules = import.meta.glob('../../../assets/icons/*.svg', {
|
|
8
|
+
eager: true,
|
|
9
|
+
query: '?react',
|
|
10
|
+
}) as Record<string, SvgModule>
|
|
11
|
+
|
|
12
|
+
// Build a name → component map: "check" → check component, "arrow-left" → arrowLeft component
|
|
13
|
+
function toCamelCase(str: string) {
|
|
14
|
+
const parts = str.split('-')
|
|
15
|
+
return (
|
|
16
|
+
parts[0] +
|
|
17
|
+
parts
|
|
18
|
+
.slice(1)
|
|
19
|
+
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
20
|
+
.join('')
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const icons: Record<string, FC<SVGProps<SVGSVGElement>>> = {}
|
|
25
|
+
for (const [path, mod] of Object.entries(svgModules) as [string, SvgModule][]) {
|
|
26
|
+
const filename = path.split('/').pop()?.replace('.svg', '') ?? ''
|
|
27
|
+
const name = toCamelCase(filename)
|
|
28
|
+
icons[name] = mod.default
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { icons }
|
|
32
|
+
|
|
33
|
+
export type IconName = keyof typeof icons
|
|
34
|
+
|
|
35
|
+
export interface IconProps extends SVGProps<SVGSVGElement> {
|
|
36
|
+
name: IconName
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function Icon({ name, className, ...props }: IconProps) {
|
|
40
|
+
const Component = icons[name]
|
|
41
|
+
if (!Component) return null
|
|
42
|
+
return <Component className={cn('zd:text-greyScale', className)} {...props} />
|
|
43
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from 'react'
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../utils/common'
|
|
4
|
+
import { Icon, type IconName } from '../Icon'
|
|
5
|
+
import { Wrapper } from '../Wrapper'
|
|
6
|
+
|
|
7
|
+
export interface IconButtonProps
|
|
8
|
+
extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
9
|
+
iconName: IconName
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function IconButton({ iconName, className, ...rest }: IconButtonProps) {
|
|
13
|
+
return (
|
|
14
|
+
<Wrapper className={cn('zd:h-13 zd:w-13 zd:rounded-2xl', className)}>
|
|
15
|
+
<button
|
|
16
|
+
type="button"
|
|
17
|
+
className="zd:flex zd:items-center zd:justify-center zd:flex-1 zd:h-full zd:w-full zd:cursor-pointer zd:hover:bg-white/20 zd:active:bg-white/30 zd:transition-colors"
|
|
18
|
+
{...rest}
|
|
19
|
+
>
|
|
20
|
+
<Icon name={iconName} className="zd:h-6 zd:w-6 zd:text-greyScale" />
|
|
21
|
+
</button>
|
|
22
|
+
</Wrapper>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type InputHTMLAttributes,
|
|
3
|
+
type TextareaHTMLAttributes,
|
|
4
|
+
useState,
|
|
5
|
+
} from 'react'
|
|
6
|
+
|
|
7
|
+
import { cn } from '../../utils/common'
|
|
8
|
+
import { Icon, type IconName } from '../Icon'
|
|
9
|
+
import { Wrapper } from '../Wrapper'
|
|
10
|
+
|
|
11
|
+
type Variant = 'default' | 'ghost' | 'listItemStyle'
|
|
12
|
+
|
|
13
|
+
export interface InputProps
|
|
14
|
+
extends Omit<InputHTMLAttributes<HTMLInputElement>, 'children'> {
|
|
15
|
+
variant?: Variant
|
|
16
|
+
multiline?: boolean
|
|
17
|
+
iconName?: IconName
|
|
18
|
+
children?: React.ReactNode
|
|
19
|
+
containerClassName?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function getHeightClass(multiline: boolean | undefined, variant: Variant) {
|
|
23
|
+
if (multiline) return 'zd:h-32 zd:py-3'
|
|
24
|
+
if (variant === 'listItemStyle') return 'zd:h-[68px]'
|
|
25
|
+
return 'zd:h-11'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function InputIcon({
|
|
29
|
+
variant,
|
|
30
|
+
iconName,
|
|
31
|
+
}: {
|
|
32
|
+
variant: Variant
|
|
33
|
+
iconName: IconName
|
|
34
|
+
}) {
|
|
35
|
+
if (variant === 'listItemStyle') {
|
|
36
|
+
return (
|
|
37
|
+
<div className="zd:w-13 zd:h-13 zd:shrink-0 zd:bg-white zd:rounded-2xl zd:flex zd:items-center zd:justify-center">
|
|
38
|
+
<Icon name={iconName} className="zd:w-6 zd:h-6 zd:text-greyScale" />
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
return (
|
|
43
|
+
<Icon
|
|
44
|
+
name={iconName}
|
|
45
|
+
className="zd:w-5 zd:h-5 zd:shrink-0 zd:text-greyScale/50"
|
|
46
|
+
/>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// `min-w-0` is required so the input doesn't claim its intrinsic content
|
|
51
|
+
// width on mobile browsers (Chrome on Android most visibly), which would
|
|
52
|
+
// squash the leading icon and the trailing chevron-button child.
|
|
53
|
+
const baseInputClass =
|
|
54
|
+
'zd:flex-1 zd:min-w-0 zd:px-0 zd:text-gray-900 zd:font-medium zd:outline-none zd:bg-transparent zd:min-h-11 zd:placeholder:text-gray-900/50 zd:caret-gray-900'
|
|
55
|
+
|
|
56
|
+
export function Input({
|
|
57
|
+
variant = 'default',
|
|
58
|
+
multiline,
|
|
59
|
+
iconName,
|
|
60
|
+
children,
|
|
61
|
+
className,
|
|
62
|
+
containerClassName,
|
|
63
|
+
onFocus,
|
|
64
|
+
onBlur,
|
|
65
|
+
...inputProps
|
|
66
|
+
}: InputProps) {
|
|
67
|
+
const [isFocused, setIsFocused] = useState(false)
|
|
68
|
+
|
|
69
|
+
const handleFocus = (
|
|
70
|
+
e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>,
|
|
71
|
+
) => {
|
|
72
|
+
setIsFocused(true)
|
|
73
|
+
onFocus?.(e as React.FocusEvent<HTMLInputElement>)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const handleBlur = (
|
|
77
|
+
e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>,
|
|
78
|
+
) => {
|
|
79
|
+
setIsFocused(false)
|
|
80
|
+
onBlur?.(e as React.FocusEvent<HTMLInputElement>)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const inputElement = multiline ? (
|
|
84
|
+
<textarea
|
|
85
|
+
{...(inputProps as unknown as TextareaHTMLAttributes<HTMLTextAreaElement>)}
|
|
86
|
+
onFocus={handleFocus}
|
|
87
|
+
onBlur={handleBlur}
|
|
88
|
+
className={cn(baseInputClass, 'zd:resize-none zd:h-full', className)}
|
|
89
|
+
/>
|
|
90
|
+
) : (
|
|
91
|
+
<input
|
|
92
|
+
{...inputProps}
|
|
93
|
+
onFocus={handleFocus}
|
|
94
|
+
onBlur={handleBlur}
|
|
95
|
+
className={cn(baseInputClass, 'zd:h-full', className)}
|
|
96
|
+
/>
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if (variant === 'ghost') {
|
|
100
|
+
return multiline ? (
|
|
101
|
+
<textarea
|
|
102
|
+
{...(inputProps as unknown as TextareaHTMLAttributes<HTMLTextAreaElement>)}
|
|
103
|
+
onFocus={
|
|
104
|
+
onFocus as TextareaHTMLAttributes<HTMLTextAreaElement>['onFocus']
|
|
105
|
+
}
|
|
106
|
+
onBlur={onBlur as TextareaHTMLAttributes<HTMLTextAreaElement>['onBlur']}
|
|
107
|
+
className={cn(
|
|
108
|
+
baseInputClass,
|
|
109
|
+
'zd:w-full zd:pl-4 zd:pr-2 zd:resize-none',
|
|
110
|
+
className,
|
|
111
|
+
)}
|
|
112
|
+
/>
|
|
113
|
+
) : (
|
|
114
|
+
<input
|
|
115
|
+
{...inputProps}
|
|
116
|
+
onFocus={onFocus}
|
|
117
|
+
onBlur={onBlur}
|
|
118
|
+
className={cn(baseInputClass, 'zd:w-full zd:pl-4 zd:pr-2', className)}
|
|
119
|
+
/>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const heightClass = getHeightClass(multiline, variant)
|
|
124
|
+
const paddingLeft = variant === 'listItemStyle' ? 'zd:pl-2' : 'zd:pl-4'
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<Wrapper
|
|
128
|
+
data-testid="input-wrapper"
|
|
129
|
+
className={cn(
|
|
130
|
+
'zd:relative zd:flex zd:w-full zd:rounded-2xl zd:items-center zd:gap-3 zd:pr-2',
|
|
131
|
+
heightClass,
|
|
132
|
+
paddingLeft,
|
|
133
|
+
containerClassName,
|
|
134
|
+
)}
|
|
135
|
+
variant="soft"
|
|
136
|
+
>
|
|
137
|
+
{/* On focus, overlay a white/20 tint over the soft (white/0.5) base so the
|
|
138
|
+
field matches the button hover state. */}
|
|
139
|
+
{isFocused && (
|
|
140
|
+
<div className="zd:absolute zd:inset-0 zd:bg-white/20 zd:pointer-events-none" />
|
|
141
|
+
)}
|
|
142
|
+
{iconName && <InputIcon variant={variant} iconName={iconName} />}
|
|
143
|
+
{inputElement}
|
|
144
|
+
{children}
|
|
145
|
+
</Wrapper>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { ButtonHTMLAttributes } from 'react'
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../utils/common'
|
|
4
|
+
import { Badge, type BadgeProps } from '../Badge'
|
|
5
|
+
import { Icon, type IconName } from '../Icon'
|
|
6
|
+
import { Text } from '../Text'
|
|
7
|
+
import { Wrapper } from '../Wrapper'
|
|
8
|
+
|
|
9
|
+
interface ListItemSkeletonProps {
|
|
10
|
+
className?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function ListItemSkeleton({ className }: ListItemSkeletonProps) {
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
className={cn(
|
|
17
|
+
'zd:w-full zd:h-[68px] zd:rounded-2xl zd:border-offWhite zd:border-[0.3px]',
|
|
18
|
+
className,
|
|
19
|
+
)}
|
|
20
|
+
>
|
|
21
|
+
<div className="zd:flex zd:flex-row zd:justify-between zd:items-center zd:p-2">
|
|
22
|
+
<div className="zd:flex zd:flex-row zd:items-center zd:gap-3">
|
|
23
|
+
<div className="zd:w-[52px] zd:h-[52px] zd:rounded-2xl zd:bg-offWhite/50 zd:animate-pulse" />
|
|
24
|
+
<div className="zd:gap-2">
|
|
25
|
+
<div className="zd:w-14 zd:h-3 zd:rounded-lg zd:bg-offWhite/50 zd:animate-pulse zd:mb-2" />
|
|
26
|
+
<div className="zd:w-14 zd:h-3 zd:rounded-lg zd:bg-offWhite/50 zd:animate-pulse" />
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
<div className="zd:gap-2">
|
|
30
|
+
<div className="zd:w-14 zd:h-3 zd:rounded-lg zd:bg-offWhite/50 zd:animate-pulse zd:mb-2" />
|
|
31
|
+
<div className="zd:w-14 zd:h-3 zd:rounded-lg zd:bg-offWhite/50 zd:animate-pulse" />
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ListItemProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
39
|
+
iconName?: IconName
|
|
40
|
+
imageUri?: string
|
|
41
|
+
title: string
|
|
42
|
+
subtitle?: string
|
|
43
|
+
badgeProps?: BadgeProps
|
|
44
|
+
details?: { text: string; subtext?: string }
|
|
45
|
+
chevron?: boolean
|
|
46
|
+
alert?: boolean
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function ListItem({
|
|
50
|
+
iconName,
|
|
51
|
+
imageUri,
|
|
52
|
+
title,
|
|
53
|
+
subtitle,
|
|
54
|
+
badgeProps,
|
|
55
|
+
details,
|
|
56
|
+
chevron,
|
|
57
|
+
alert,
|
|
58
|
+
className,
|
|
59
|
+
...rest
|
|
60
|
+
}: ListItemProps) {
|
|
61
|
+
return (
|
|
62
|
+
<Wrapper
|
|
63
|
+
className={cn(
|
|
64
|
+
'zd:w-full zd:h-[68px] zd:rounded-2xl',
|
|
65
|
+
alert && 'zd:border-0',
|
|
66
|
+
className,
|
|
67
|
+
)}
|
|
68
|
+
>
|
|
69
|
+
<button
|
|
70
|
+
type="button"
|
|
71
|
+
className={cn(
|
|
72
|
+
'zd:w-full zd:flex zd:flex-row zd:justify-between zd:items-center zd:p-2 zd:transition-colors zd:cursor-pointer',
|
|
73
|
+
alert
|
|
74
|
+
? 'zd:bg-solarOrange/15'
|
|
75
|
+
: 'zd:hover:bg-white/20 zd:active:bg-white/30',
|
|
76
|
+
rest.disabled && 'zd:opacity-50 zd:cursor-not-allowed',
|
|
77
|
+
)}
|
|
78
|
+
{...rest}
|
|
79
|
+
>
|
|
80
|
+
<div className="zd:flex zd:flex-row zd:items-center zd:gap-3">
|
|
81
|
+
<div
|
|
82
|
+
className={cn(
|
|
83
|
+
'zd:w-[52px] zd:h-[52px] zd:rounded-2xl zd:flex zd:items-center zd:justify-center zd:shrink-0',
|
|
84
|
+
alert ? 'zd:bg-offWhite/50' : 'zd:bg-white',
|
|
85
|
+
)}
|
|
86
|
+
>
|
|
87
|
+
{imageUri ? (
|
|
88
|
+
<img src={imageUri} alt="" className="zd:w-6 zd:h-6" />
|
|
89
|
+
) : iconName ? (
|
|
90
|
+
<Icon
|
|
91
|
+
name={iconName}
|
|
92
|
+
className={cn(
|
|
93
|
+
'zd:w-6 zd:h-6',
|
|
94
|
+
details || alert
|
|
95
|
+
? 'zd:text-solarOrange'
|
|
96
|
+
: 'zd:text-greyScale',
|
|
97
|
+
)}
|
|
98
|
+
/>
|
|
99
|
+
) : null}
|
|
100
|
+
</div>
|
|
101
|
+
<div
|
|
102
|
+
className={cn(
|
|
103
|
+
'zd:flex zd:flex-col zd:justify-center zd:text-left',
|
|
104
|
+
badgeProps ? 'zd:gap-2' : 'zd:gap-1',
|
|
105
|
+
)}
|
|
106
|
+
>
|
|
107
|
+
<Text className="zd:text-body1">{title}</Text>
|
|
108
|
+
{subtitle && (
|
|
109
|
+
<Text className="zd:text-body3 zd:text-greyScale/50">
|
|
110
|
+
{subtitle}
|
|
111
|
+
</Text>
|
|
112
|
+
)}
|
|
113
|
+
{badgeProps && <Badge {...badgeProps} />}
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
{details ? (
|
|
117
|
+
<div className="zd:flex zd:flex-col zd:pr-1">
|
|
118
|
+
<Text className="zd:text-body1">{details.text}</Text>
|
|
119
|
+
{details.subtext && (
|
|
120
|
+
<Text className="zd:text-body3 zd:text-greyScale/50 zd:self-end">
|
|
121
|
+
{details.subtext}
|
|
122
|
+
</Text>
|
|
123
|
+
)}
|
|
124
|
+
</div>
|
|
125
|
+
) : chevron ? (
|
|
126
|
+
<div className="zd:w-13 zd:h-13 zd:flex zd:items-center zd:justify-center">
|
|
127
|
+
<Icon
|
|
128
|
+
name="chevronRight"
|
|
129
|
+
className="zd:h-6 zd:w-6 zd:text-greyScale"
|
|
130
|
+
/>
|
|
131
|
+
</div>
|
|
132
|
+
) : null}
|
|
133
|
+
</button>
|
|
134
|
+
</Wrapper>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cn } from '../../utils/common'
|
|
2
|
+
import { Text } from '../Text'
|
|
3
|
+
import { Wrapper } from '../Wrapper'
|
|
4
|
+
|
|
5
|
+
export interface SwitchProps {
|
|
6
|
+
value?: boolean
|
|
7
|
+
onValueChange?: () => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Switch({ value, onValueChange }: SwitchProps) {
|
|
11
|
+
return (
|
|
12
|
+
<Wrapper variant="ghost" className="zd:w-14 zd:h-7 zd:rounded-xl zd:p-1">
|
|
13
|
+
<button
|
|
14
|
+
type="button"
|
|
15
|
+
role="switch"
|
|
16
|
+
aria-checked={value ?? false}
|
|
17
|
+
onClick={onValueChange}
|
|
18
|
+
className="zd:flex zd:items-center zd:justify-center zd:flex-row zd:gap-1.5 zd:w-full zd:h-full zd:rounded-lg zd:bg-white/70 zd:cursor-pointer"
|
|
19
|
+
>
|
|
20
|
+
{value && (
|
|
21
|
+
<Text className="zd:text-body3 zd:text-greyScale/90">On</Text>
|
|
22
|
+
)}
|
|
23
|
+
<div
|
|
24
|
+
className={cn(
|
|
25
|
+
'zd:w-3.5 zd:h-3.5 zd:rounded-full zd:shadow-sm',
|
|
26
|
+
value ? 'zd:bg-solarOrange' : 'zd:bg-greyScale/30',
|
|
27
|
+
)}
|
|
28
|
+
/>
|
|
29
|
+
{!value && (
|
|
30
|
+
<Text className="zd:text-body3 zd:text-greyScale/50">Off</Text>
|
|
31
|
+
)}
|
|
32
|
+
</button>
|
|
33
|
+
</Wrapper>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, HTMLAttributes } from 'react'
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../utils/common'
|
|
4
|
+
|
|
5
|
+
export type TextProps =
|
|
6
|
+
| ({ as?: 'p' | 'span' | 'label' } & HTMLAttributes<HTMLElement>)
|
|
7
|
+
| ({ as: 'a' } & AnchorHTMLAttributes<HTMLAnchorElement>)
|
|
8
|
+
|
|
9
|
+
export function Text({ as: Tag = 'p', className, ...props }: TextProps) {
|
|
10
|
+
return (
|
|
11
|
+
<Tag
|
|
12
|
+
className={cn(
|
|
13
|
+
'zd:font-medium zd:font-sans zd:text-body2 zd:text-greyScale',
|
|
14
|
+
className,
|
|
15
|
+
)}
|
|
16
|
+
{...(props as HTMLAttributes<HTMLElement> &
|
|
17
|
+
AnchorHTMLAttributes<HTMLAnchorElement>)}
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
20
|
+
}
|