From 40de54b0101bdfd37f577d18c10ec9f1ab1ce8fe Mon Sep 17 00:00:00 2001
From: Kasper Fabricius Kristensen
<45367945+kasperkristensen@users.noreply.github.com>
Date: Fri, 3 Mar 2023 10:09:16 +0100
Subject: [PATCH] feat(admin,admin-ui,medusa): Add Medusa Admin plugin (#3334)
---
.changeset/sixty-jeans-fold.md | 7 +
.eslintignore | 2 +
.eslintrc.js | 56 +-
.prettierrc | 10 +-
integration-tests/api/package.json | 3 +-
integration-tests/plugins/package.json | 3 +-
integration-tests/repositories/package.json | 3 +-
package.json | 7 +-
packages/admin-ui/.gitignore | 4 +
packages/admin-ui/.npmignore | 6 +
packages/admin-ui/README.md | 38 +
packages/admin-ui/package.json | 90 +
packages/admin-ui/src/index.ts | 28 +
packages/admin-ui/src/types/build.ts | 15 +
packages/admin-ui/src/types/config.ts | 5 +
packages/admin-ui/src/types/index.ts | 2 +
packages/admin-ui/src/types/misc.ts | 9 +
packages/admin-ui/src/utils/format-base.ts | 5 +
.../src/utils/get-custom-vite-config.ts | 76 +
packages/admin-ui/src/utils/index.ts | 2 +
packages/admin-ui/tsconfig.json | 18 +
packages/admin-ui/ui/index.html | 13 +
packages/admin-ui/ui/postcss.config.js | 9 +
packages/admin-ui/ui/public/logo.svg | 10 +
packages/admin-ui/ui/src/App.tsx | 45 +
.../ui/src/assets/styles/emoji-picker.css | 107 +
.../admin-ui/ui/src/assets/styles/global.css | 456 ++
.../admin-ui/ui/src/assets/svg/carrot.svg | 5 +
.../admin-ui/ui/src/assets/svg/controller.svg | 7 +
packages/admin-ui/ui/src/assets/svg/flag.svg | 4 +
packages/admin-ui/ui/src/assets/svg/happy.svg | 6 +
packages/admin-ui/ui/src/assets/svg/heart.svg | 3 +
.../admin-ui/ui/src/assets/svg/lightbulb.svg | 5 +
packages/admin-ui/ui/src/assets/svg/plane.svg | 3 +
.../admin-ui/ui/src/assets/svg/search.svg | 3 +
.../admin-ui/ui/src/assets/svg/sprout.svg | 6 +
packages/admin-ui/ui/src/assets/svg/star.svg | 3 +
.../ui/src/components/atoms/avatar/index.tsx | 62 +
.../components/atoms/back-button/index.tsx | 29 +
.../src/components/atoms/checkbox/index.tsx | 32 +
.../atoms/copy-to-clipboard/index.tsx | 58 +
.../atoms/date-picker/custom-header.tsx | 44 +
.../atoms/date-picker/date-picker.tsx | 115 +
.../atoms/date-picker/time-picker.tsx | 102 +
.../components/atoms/date-picker/types.tsx | 6 +
.../src/components/atoms/date-picker/utils.ts | 25 +
.../components/atoms/fade-wrapper/index.tsx | 47 +
.../atoms/file-upload-field/index.tsx | 105 +
.../atoms/includes-tax-tooltip/index.tsx | 26 +
.../components/atoms/input-error/index.tsx | 73 +
.../atoms/loading-container/index.tsx | 32 +
.../components/atoms/notification/index.tsx | 62 +
.../atoms/number-scroller/index.tsx | 47 +
.../components/atoms/os-shortcut/index.tsx | 50 +
.../atoms/page-description/index.tsx | 20 +
.../atoms/save-notification/error-state.tsx | 49 +
.../atoms/save-notification/index.tsx | 94 +
.../atoms/save-notification/saving-state.tsx | 30 +
.../atoms/save-notification/success-state.tsx | 49 +
.../components/atoms/settings-card/index.tsx | 56 +
.../src/components/atoms/skeleton/index.tsx | 25 +
.../ui/src/components/atoms/spinner.tsx | 35 +
.../ui/src/components/atoms/switch/index.tsx | 26 +
.../src/components/atoms/text-input/index.tsx | 19 +
.../src/components/atoms/thumbnail/index.ts | 1 +
.../components/atoms/thumbnail/thumbnail.tsx | 30 +
.../atoms/toaster-container/index.tsx | 33 +
.../ui/src/components/atoms/tooltip/index.tsx | 58 +
.../atoms/two-step-delete/index.tsx | 110 +
.../components/declarative-toaster/index.tsx | 23 +
.../components/fundamentals/badge/index.tsx | 43 +
.../components/fundamentals/button/index.tsx | 71 +
.../fundamentals/details-icon/contact.svg | 7 +
.../fundamentals/details-icon/index.tsx | 57 +
.../fundamentals/feature-toggle.tsx | 21 +
.../fundamentals/icon-badge/index.tsx | 36 +
.../fundamentals/icons/alert-icon/index.tsx | 43 +
.../fundamentals/icons/arrow-down-icon.tsx | 36 +
.../icons/arrow-left-icon/index.tsx | 35 +
.../icons/arrow-right-icon/index.tsx | 36 +
.../icons/arrow-top-right-icon/index.tsx | 29 +
.../fundamentals/icons/arrow-up-icon.tsx | 36 +
.../fundamentals/icons/back-icon/index.tsx | 36 +
.../icons/backspace-icon/index.tsx | 42 +
.../fundamentals/icons/bell-icon/index.tsx | 36 +
.../icons/bell-noti-icon/index.tsx | 41 +
.../icons/bell-off-icon/index.tsx | 57 +
.../icons/buildings-icon/index.tsx | 64 +
.../fundamentals/icons/cancel-icon/index.tsx | 36 +
.../fundamentals/icons/cart-icon/index.tsx | 49 +
.../fundamentals/icons/cash-icon/index.tsx | 99 +
.../fundamentals/icons/channels-icon.tsx | 65 +
.../icons/check-circle-fill-icon/index.tsx | 28 +
.../icons/check-circle-icon/index.tsx | 36 +
.../fundamentals/icons/check-icon.tsx | 29 +
.../fundamentals/icons/chevron-down.tsx | 29 +
.../icons/chevron-left-icon/index.tsx | 29 +
.../icons/chevron-right-icon/index.tsx | 29 +
.../fundamentals/icons/chevron-up.tsx | 29 +
.../icons/clipboard-copy-icon/index.tsx | 50 +
.../fundamentals/icons/clock-icon/index.tsx | 36 +
.../fundamentals/icons/coins-icon/index.tsx | 50 +
.../icons/corner-down-right-icon/index.tsx | 36 +
.../fundamentals/icons/cross-icon/index.tsx | 36 +
.../icons/crosshair-icon/index.tsx | 57 +
.../icons/customer-icon/index.tsx | 36 +
.../fundamentals/icons/details-icon.tsx | 57 +
.../fundamentals/icons/discord-icon.tsx | 26 +
.../icons/dollar-sign-icon/index.tsx | 36 +
.../fundamentals/icons/down-left/index.tsx | 34 +
.../fundamentals/icons/download-icon.tsx | 42 +
.../fundamentals/icons/duplicate-icon.tsx | 36 +
.../fundamentals/icons/edit-icon.tsx | 36 +
.../fundamentals/icons/edit-icon/index.tsx | 36 +
.../fundamentals/icons/export-icon/index.tsx | 43 +
.../fundamentals/icons/eye-icon/index.tsx | 36 +
.../fundamentals/icons/eye-off-icon/index.tsx | 36 +
.../icons/fast-delivery-icon/index.tsx | 64 +
.../fundamentals/icons/file-icon.tsx | 55 +
.../fundamentals/icons/gear-icon/index.tsx | 36 +
.../fundamentals/icons/gift-icon/index.tsx | 57 +
.../fundamentals/icons/grip-icon.tsx | 64 +
.../fundamentals/icons/happy-icon/index.tsx | 50 +
.../fundamentals/icons/help-circle.tsx | 43 +
.../icons/image-placeholder-icon/index.tsx | 43 +
.../fundamentals/icons/info-icon/index.tsx | 43 +
.../fundamentals/icons/key-icon.tsx | 30 +
.../icons/list-arrow-icon/index.tsx | 57 +
.../fundamentals/icons/list-icon.tsx | 64 +
.../fundamentals/icons/lock-icon/index.tsx | 36 +
.../fundamentals/icons/log-out-icon/index.tsx | 43 +
.../icons/long-arrow-right-icon/index.tsx | 38 +
.../fundamentals/icons/mail-icon/index.tsx | 36 +
.../fundamentals/icons/map-pin-icon/index.tsx | 36 +
.../fundamentals/icons/medusa-icon/index.tsx | 23 +
.../fundamentals/icons/medusa-vice/index.tsx | 39 +
.../fundamentals/icons/minus-icon/index.tsx | 29 +
.../icons/more-horizontal-icon.tsx | 43 +
.../fundamentals/icons/package-icon/index.tsx | 50 +
.../fundamentals/icons/percent-icon/index.tsx | 43 +
.../fundamentals/icons/plus-icon/index.tsx | 36 +
.../fundamentals/icons/pointer-icon/index.tsx | 35 +
.../fundamentals/icons/publish-icon/index.tsx | 57 +
.../fundamentals/icons/refresh-icon.tsx | 50 +
.../components/fundamentals/icons/refund.tsx | 57 +
.../icons/sad-face-icon/index.tsx | 51 +
.../fundamentals/icons/sale-icon/index.tsx | 50 +
.../fundamentals/icons/search-icon/index.tsx | 27 +
.../fundamentals/icons/send-icon/index.tsx | 33 +
.../icons/sided-mouth-face/index.tsx | 51 +
.../fundamentals/icons/sorting-icon/index.tsx | 54 +
.../icons/sparkles-icon/index.tsx | 29 +
.../fundamentals/icons/stop-icon.tsx | 36 +
.../fundamentals/icons/tag-icon/index.tsx | 36 +
.../fundamentals/icons/taxes-icon.tsx | 54 +
.../fundamentals/icons/tile-icon.tsx | 50 +
.../fundamentals/icons/trash-icon.tsx | 50 +
.../icons/triangle-right-icon/index.tsx | 28 +
.../fundamentals/icons/truck-icon/index.tsx | 43 +
.../fundamentals/icons/types/icon-type.ts | 8 +
.../fundamentals/icons/u-turn-icon.tsx | 29 +
.../icons/unpublish-icon/index.tsx | 57 +
.../fundamentals/icons/upload-icon/index.tsx | 43 +
.../fundamentals/icons/users-icon/index.tsx | 50 +
.../fundamentals/icons/warning-circle.tsx | 42 +
.../fundamentals/icons/x-circle-icon.tsx | 43 +
.../fundamentals/image-placeholder.tsx | 11 +
.../fundamentals/input-container.tsx | 37 +
.../components/fundamentals/input-header.tsx | 38 +
.../fundamentals/status-indicator/index.tsx | 34 +
.../src/components/molecules/actionables.tsx | 115 +
.../molecules/activity-card/index.tsx | 88 +
.../amount-and-currency-input.tsx | 134 +
.../molecules/amount-input/amount-input.tsx | 92 +
.../molecules/amount-input/index.ts | 4 +
.../molecules/availability-duration/index.tsx | 86 +
.../molecules/banner-card/index.tsx | 73 +
.../molecules/batch-job-file-card/index.tsx | 42 +
.../components/molecules/breadcrumb/index.tsx | 42 +
.../molecules/collapsible-tree/index.tsx | 187 +
.../components/molecules/connected-form.tsx | 20 +
.../molecules/customer-avatar-item/index.tsx | 34 +
.../customers-groups-summary/index.tsx | 33 +
.../molecules/emoji-picker/index.tsx | 41 +
.../molecules/filter-dropdown/container.tsx | 89 +
.../molecules/filter-dropdown/item.tsx | 551 ++
.../molecules/filter-dropdown/save-field.tsx | 45 +
.../components/molecules/filter-tab/index.tsx | 62 +
.../molecules/form-error-toaster/index.tsx | 41 +
.../molecules/form-toaster/index.tsx | 177 +
.../molecules/generating-input/index.tsx | 93 +
.../components/molecules/grid-input/index.tsx | 15 +
.../molecules/hot-key-action/index.tsx | 23 +
.../molecules/icon-tooltip/index.tsx | 36 +
.../indeterminate-checkbox/index.tsx | 82 +
.../molecules/input-signin/index.tsx | 99 +
.../src/components/molecules/input/index.tsx | 155 +
.../components/molecules/json-view/index.tsx | 94 +
.../molecules/modal/focus-modal.tsx | 114 +
.../src/components/molecules/modal/index.tsx | 161 +
.../molecules/modal/layered-modal.tsx | 163 +
.../components/molecules/modal/side-modal.tsx | 60 +
.../molecules/modal/stepped-modal.tsx | 227 +
.../molecules/native-select/index.tsx | 68 +
.../components/molecules/note-input/index.tsx | 76 +
.../molecules/notification-bell/index.tsx | 21 +
.../molecules/numbered-item/index.tsx | 52 +
.../molecules/order-status/index.tsx | 113 +
.../molecules/rma-select-shipping/index.tsx | 54 +
.../sales-channels-display/index.tsx | 70 +
.../molecules/sales-channels-list/index.tsx | 46 +
.../sales-channels-summary/index.tsx | 39 +
.../src/components/molecules/search-bar.tsx | 49 +
.../components/molecules/section/index.tsx | 32 +
.../src/components/molecules/select/index.tsx | 235 +
.../next-select/components/containers.tsx | 190 +
.../select/next-select/components/control.tsx | 149 +
.../select/next-select/components/index.ts | 39 +
.../select/next-select/components/input.tsx | 36 +
.../select/next-select/components/menu.tsx | 343 ++
.../next-select/components/multi-value.tsx | 113 +
.../next-select/components/placeholder.tsx | 33 +
.../components/select-primitives.ts | 3 +
.../next-select/components/single-value.tsx | 42 +
.../next-select/createable-select/index.tsx | 40 +
.../molecules/select/next-select/index.tsx | 4 +
.../select/next-select/module-augmentation.ts | 74 +
.../select/next-select/select/index.tsx | 62 +
.../select/next-select/use-select-props.tsx | 85 +
.../molecules/select/next-select/utils.tsx | 83 +
.../molecules/select/select-components.tsx | 314 ++
.../molecules/shipping-option/index.tsx | 70 +
.../molecules/sidebar-company-logo/index.tsx | 20 +
.../molecules/sidebar-menu-item/index.tsx | 72 +
.../molecules/sidebar-team-member/index.tsx | 28 +
.../molecules/status-selector/index.tsx | 55 +
.../molecules/switchable-item/index.tsx | 55 +
.../molecules/table-fileds-filter/index.tsx | 200 +
.../molecules/table-pagination/index.ts | 1 +
.../table-pagination/table-pagination.tsx | 77 +
.../molecules/table-toaster/index.tsx | 27 +
.../molecules/table/filtering-option.tsx | 96 +
.../src/components/molecules/table/index.tsx | 250 +
.../molecules/table/table-search.tsx | 47 +
.../molecules/tag-grid.tsx/index.tsx | 38 +
.../components/molecules/tag-input/index.tsx | 231 +
.../components/molecules/textarea/index.tsx | 114 +
.../timeline-events/claim-event/index.tsx | 269 +
.../timeline-events/event-actionables.tsx | 20 +
.../timeline-events/event-container.tsx | 105 +
.../timeline-events/event-item-container.tsx | 40 +
.../molecules/timeline-events/event-type.ts | 5 +
.../molecules/timeline-events/exchange.tsx | 338 ++
.../timeline-events/items-fulfilled.tsx | 32 +
.../timeline-events/items-shipped.tsx | 32 +
.../molecules/timeline-events/note.tsx | 73 +
.../timeline-events/notification/index.tsx | 66 +
.../notification/resend-modal.tsx | 99 +
.../timeline-events/order-canceled.tsx | 20 +
.../timeline-events/order-edit/canceled.tsx | 26 +
.../timeline-events/order-edit/confirmed.tsx | 40 +
.../timeline-events/order-edit/created.tsx | 292 ++
.../timeline-events/order-edit/declined.tsx | 46 +
.../timeline-events/order-edit/index.tsx | 27 +
.../order-edit/payment-required.tsx | 80 +
.../order-edit/refund-required.tsx | 73 +
.../timeline-events/order-edit/requested.tsx | 62 +
.../timeline-events/order-placed.tsx | 29 +
.../molecules/timeline-events/refund.tsx | 43 +
.../molecules/timeline-events/return.tsx | 151 +
.../components/molecules/user-menu/index.tsx | 75 +
.../components/organisms/accordion/index.tsx | 113 +
.../organisms/activity-drawer/index.tsx | 72 +
.../add-denomination-modal/index.tsx | 266 +
.../use-values-field-array.ts | 72 +
.../organisms/analytics-config-form/index.tsx | 81 +
.../organisms/analytics-preferences/index.tsx | 139 +
.../batch-jobs-activity-list/index.tsx | 247 +
.../batch-jobs-activity-list/utils.ts | 48 +
.../ui/src/components/organisms/body-card.tsx | 115 +
.../organisms/confirmation-prompt.tsx | 71 +
.../organisms/currency-input/index.tsx | 296 ++
.../organisms/custom-table-header/index.tsx | 37 +
.../components/organisms/delete-prompt.tsx | 78 +
.../organisms/details-collapsible/index.tsx | 50 +
.../edit-denominations-modal/index.tsx | 179 +
.../organisms/edit-user-modal/index.tsx | 123 +
.../organisms/error-boundary/index.tsx | 163 +
.../organisms/export-modal/index.tsx | 62 +
.../organisms/file-upload-modal/index.tsx | 32 +
.../organisms/gift-card-banner/index.tsx | 96 +
.../organisms/help-dialog/index.tsx | 86 +
.../organisms/invite-modal/index.tsx | 112 +
.../components/organisms/login-card/index.tsx | 82 +
.../organisms/medusa-price-input/index.tsx | 51 +
.../components/organisms/metadata/index.tsx | 148 +
.../organisms/price-input/index.tsx | 65 +
.../organisms/product-variant-tree/index.tsx | 85 +
.../organisms/radio-group/index.tsx | 174 +
.../components/organisms/raw-json/index.tsx | 38 +
.../organisms/reset-token-card/index.tsx | 115 +
.../rma-return-product-table/index.tsx | 114 +
.../rma-select-product-table/index.tsx | 303 ++
.../components/organisms/section/index.tsx | 52 +
.../components/organisms/sidebar/index.tsx | 110 +
.../organisms/table-container/index.tsx | 50 +
.../organisms/table-container/pagination.tsx | 64 +
.../organisms/table-container/types.ts | 12 +
.../components/organisms/timeline/index.tsx | 212 +
.../src/components/organisms/topbar/index.tsx | 62 +
.../organisms/upload-modal/index.tsx | 302 ++
.../ui/src/components/private-route/index.tsx | 31 +
.../admin-ui/ui/src/components/seo/index.tsx | 75 +
.../templates/add-products-modal/index.tsx | 109 +
.../product-table-config.tsx | 88 +
.../templates/add-products-modal/utils.ts | 32 +
.../src/components/templates/address-form.tsx | 180 +
.../templates/collection-modal/index.tsx | 191 +
.../add-product-table.tsx | 233 +
.../collection-product-table/index.tsx | 193 +
.../collection-product-table/types.ts | 11 +
.../use-collection-product-columns.tsx | 48 +
.../use-sorting-options.tsx | 88 +
.../use-view-product-columns.tsx | 59 +
.../collection-product-table/utils.tsx | 25 +
.../view-products-table.tsx | 194 +
.../templates/collections-table/index.tsx | 191 +
.../use-collection-actions.tsx | 44 +
.../use-collection-column.tsx | 52 +
.../templates/customer-group-table/config.tsx | 104 +
.../customer-groups-table.tsx | 279 ++
.../customers-list-table.tsx | 231 +
.../edit-customers-table.tsx | 253 +
.../templates/customer-orders-table/index.tsx | 154 +
.../use-customer-orders-columns.tsx | 149 +
.../templates/customer-table/index.tsx | 206 +
.../customer-table/use-customer-columns.tsx | 48 +
.../customer-table/use-customer-filters.tsx | 213 +
.../discount-filter-dropdown/index.tsx | 140 +
.../templates/discount-table/index.tsx | 234 +
.../discount-table/use-copy-promotion.tsx | 74 +
.../discount-table/use-promotion-columns.tsx | 151 +
.../discount-table/use-promotion-filters.tsx | 519 ++
.../use-promotion-row-actions.tsx | 86 +
.../templates/draft-order-table/index.tsx | 166 +
.../use-draft-order-column.tsx | 82 +
.../use-draft-order-filters.ts | 213 +
.../gift-card-filter-dropdown/index.tsx | 179 +
.../templates/gift-card-table/index.tsx | 197 +
.../gift-card-table/use-gift-card-column.tsx | 103 +
.../gift-card-table/use-gift-card-filters.ts | 591 +++
.../templates/image-table/index.tsx | 163 +
.../ui/src/components/templates/layout.tsx | 30 +
.../src/components/templates/login-layout.tsx | 29 +
.../templates/order-filter-dropdown/index.tsx | 226 +
.../templates/order-table/index.tsx | 241 +
.../order-table/use-order-column.tsx | 132 +
.../order-table/use-order-filters.ts | 617 +++
.../price-list-table/price-list-filters.tsx | 133 +
.../price-list-table/price-list-table.tsx | 202 +
.../price-list-table/use-copy-price-list.tsx | 56 +
.../use-price-list-actions.tsx | 79 +
.../use-price-list-columns.tsx | 71 +
.../use-price-list-filters.tsx | 495 ++
.../templates/price-list-table/utils.tsx | 43 +
.../templates/price-overrides/index.tsx | 222 +
.../price-overrides/price-amount.tsx | 75 +
.../templates/product-table/index.tsx | 269 +
.../templates/product-table/overview.tsx | 107 +
.../product-table/use-copy-product.ts | 177 +
.../product-table/use-filter-tabs.tsx | 487 ++
.../product-table/use-product-actions.tsx | 88 +
.../product-table/use-product-column.tsx | 142 +
.../product-table/use-product-filters.ts | 604 +++
.../templates/search-modal/index.tsx | 163 +
.../search-modal/keyboard-shortcuts.tsx | 46 +
.../search-modal/results/customer-results.tsx | 69 +
.../search-modal/results/discount-results.tsx | 64 +
.../search-modal/results/order-results.tsx | 63 +
.../search-modal/results/product-results.tsx | 69 +
.../search-modal/section-collapsible.tsx | 28 +
.../use-keyboard-navigation-list.tsx | 117 +
.../templates/selectable-table/index.tsx | 211 +
.../templates/settings-overview.tsx | 18 +
.../templates/transfer-orders-modal/index.tsx | 234 +
.../components/templates/two-split-pane.tsx | 54 +
.../src/components/templates/user-table.tsx | 329 ++
.../admin-ui/ui/src/constants/analytics.ts | 1 +
.../ui/src/constants/medusa-backend-url.ts | 2 +
.../admin-ui/ui/src/constants/query-client.ts | 11 +
.../src/domain/collections/details/index.tsx | 210 +
.../ui/src/domain/collections/index.tsx | 12 +
.../ui/src/domain/customers/details/edit.tsx | 146 +
.../ui/src/domain/customers/details/index.tsx | 132 +
.../groups/context/customer-group-context.tsx | 81 +
.../customers/groups/customer-group-modal.tsx | 114 +
.../src/domain/customers/groups/details.tsx | 248 +
.../ui/src/domain/customers/groups/index.tsx | 58 +
.../ui/src/domain/customers/header.tsx | 28 +
.../ui/src/domain/customers/index.tsx | 33 +
.../add-condition/conditions-provider.tsx | 183 +
.../conditions/add-condition/index.tsx | 30 +
.../collections/add-collections.tsx | 80 +
.../collections-conditions-table.tsx | 85 +
.../customer-groups/add-customer-groups.tsx | 80 +
.../customer-groups-conditions-table.tsx | 85 +
.../product-types/add-types.tsx | 82 +
.../product-types/type-conditions-table.tsx | 85 +
.../products/add-products.tsx | 78 +
.../products/product-conditions-table.tsx | 84 +
.../add-condition-resources/tags/add-tags.tsx | 78 +
.../tags/tags-conditions-table.tsx | 83 +
.../edit-condition/add-conditions-screens.tsx | 33 +
.../condition-table-actions.tsx | 75 +
.../edit-condition/edit-condition-modal.tsx | 74 +
.../edit-condition-provider.tsx | 124 +
.../discounts/details/conditions/index.tsx | 80 +
.../conditions/use-discount-conditions.tsx | 105 +
.../configurations/edit-configurations.tsx | 242 +
.../details/configurations/index.tsx | 60 +
.../use-discount-configurations.tsx | 139 +
.../details/general/edit-general.tsx | 236 +
.../discounts/details/general/index.tsx | 176 +
.../ui/src/domain/discounts/details/index.tsx | 76 +
.../ui/src/domain/discounts/index.tsx | 54 +
.../discount-form/add-conditions-modal.tsx | 118 +
.../add-condition-footer.tsx | 69 +
.../add-condition-tables/collections.tsx | 91 +
.../add-condition-tables/customer-groups.tsx | 88 +
.../add-condition-tables/products.tsx | 84 +
.../add-condition-tables/tags.tsx | 75 +
.../add-condition-tables/types.tsx | 78 +
.../details-condition-tables/collections.tsx | 95 +
.../customer-groups.tsx | 89 +
.../details-condition-footer.tsx | 62 +
.../details-condition-tables/products.tsx | 85 +
.../details-condition-tables/tags.tsx | 77 +
.../details-condition-tables/types.tsx | 79 +
.../edit-condition-tables/collections.tsx | 86 +
.../edit-condition-tables/customer-groups.tsx | 82 +
.../edit-condition-footer.tsx | 63 +
.../edit-condition-tables/products.tsx | 78 +
.../edit-condition-tables/tags.tsx | 77 +
.../edit-condition-tables/types.tsx | 72 +
.../condition-tables/shared/collection.tsx | 70 +
.../condition-tables/shared/common.tsx | 4 +
.../shared/condition-operator.tsx | 36 +
.../condition-tables/shared/groups.tsx | 67 +
.../condition-tables/shared/products.tsx | 118 +
.../condition-tables/shared/tags.tsx | 58 +
.../condition-tables/shared/types.tsx | 58 +
.../discount-form/edit-conditions-modal.tsx | 47 +
.../form/discount-form-context.tsx | 208 +
.../new/discount-form/form/mappers.ts | 150 +
.../discount-form/form/use-form-actions.tsx | 44 +
.../discounts/new/discount-form/index.tsx | 158 +
.../sections/conditions/condition-item.tsx | 241 +
.../sections/conditions/index.tsx | 84 +
.../discount-form/sections/configuration.tsx | 235 +
.../sections/discount-allocation.tsx | 42 +
.../discount-form/sections/discount-type.tsx | 55 +
.../new/discount-form/sections/general.tsx | 186 +
.../use-condition-modal-items.tsx | 118 +
.../ui/src/domain/discounts/new/index.tsx | 14 +
.../admin-ui/ui/src/domain/discounts/types.ts | 81 +
.../ui/src/domain/discounts/utils/index.tsx | 22 +
.../src/domain/gift-cards/custom-giftcard.tsx | 164 +
.../details/edit-gift-card-modal.tsx | 111 +
.../src/domain/gift-cards/details/index.tsx | 171 +
.../details/update-balance-modal.tsx | 116 +
.../ui/src/domain/gift-cards/index.tsx | 16 +
.../gift-cards/manage/denomination-table.tsx | 119 +
.../manage/form/gift-card-form-context.tsx | 92 +
.../domain/gift-cards/manage/form/mappers.ts | 59 +
.../ui/src/domain/gift-cards/manage/index.tsx | 105 +
.../manage/sections/denominations.tsx | 126 +
.../gift-cards/manage/sections/images.tsx | 105 +
.../manage/sections/information.tsx | 227 +
.../domain/gift-cards/manage/utils/types.ts | 12 +
.../admin-ui/ui/src/domain/gift-cards/new.tsx | 294 ++
.../ui/src/domain/gift-cards/overview.tsx | 144 +
.../ui/src/domain/inventory/header.tsx | 29 +
.../ui/src/domain/inventory/index.tsx | 14 +
.../src/domain/inventory/inventory/index.tsx | 19 +
.../components/address-form/index.tsx | 150 +
.../components/edit-sales-channels/index.tsx | 76 +
.../components/general-form/index.tsx | 37 +
.../components/location-card/index.tsx | 105 +
.../components/sales-channels-form/index.tsx | 75 +
.../sales-channels-section/index.tsx | 26 +
.../domain/inventory/locations/edit/index.tsx | 114 +
.../src/domain/inventory/locations/index.tsx | 59 +
.../domain/inventory/locations/new/index.tsx | 183 +
.../admin-ui/ui/src/domain/oauth/index.tsx | 27 +
.../__tests__/claim-type-form.test.tsx | 59 +
.../components/claim-type-form/index.tsx | 46 +
.../__tests__/items-to-receive-form.test.tsx | 59 +
.../components/items-to-receive-form/index.ts | 2 +
.../items-to-receive-form.tsx | 71 +
.../items-to-receive-table.tsx | 62 +
.../use-items-to-receive-columns.tsx | 164 +
.../__tests__/items-to-return-form.test.tsx | 119 +
.../add-return-reason-screen.tsx | 132 +
.../add-return-reason/index.tsx | 90 +
.../components/items-to-return-form/index.tsx | 88 +
.../items-to-return-table.tsx | 86 +
.../use-return-item-columns.tsx | 171 +
.../__tests__/items-to-send-form.test.tsx | 80 +
.../add-additional-items-screen.tsx | 193 +
.../add-additional-items-table.tsx | 85 +
.../add-additional-items-screen/index.ts | 1 +
.../use-add-additional-items-columns.tsx | 194 +
.../additional-items-table.tsx | 71 +
.../components/items-to-send-form/index.tsx | 96 +
.../use-additional-items-columns.tsx | 156 +
.../__tests__/refund-amount-form.test.tsx | 59 +
.../components/refund-amount-form/index.tsx | 114 +
.../__tests__/claim-summary.test.tsx | 72 +
.../rma-summaries/claim-summary.tsx | 177 +
.../orders/components/rma-summaries/index.ts | 3 +
.../rma-summaries/receive-return-summary.tsx | 120 +
.../rma-summaries/summary-line-item.tsx | 58 +
.../rma-summaries/summary-shipping-line.tsx | 41 +
.../__tests__/send-notification-form.test.tsx | 52 +
.../send-notification-form/index.tsx | 46 +
.../__tests__/shipping-address-form.test.tsx | 53 +
.../shipping-address-form/index.tsx | 59 +
.../shipping-address-form-modal.tsx | 114 +
.../__tests__/shipping-form.test.tsx | 148 +
.../orders/components/shipping-form/index.tsx | 210 +
.../components/table-quantity-selector.tsx | 91 +
.../domain/orders/details/address-modal.tsx | 156 +
.../details/claim/register-claim-menu.tsx | 294 ++
.../details/create-fulfillment/index.tsx | 201 +
.../details/create-fulfillment/item-table.tsx | 161 +
.../src/domain/orders/details/email-modal.tsx | 95 +
.../ui/src/domain/orders/details/index.tsx | 677 +++
.../orders/details/mark-shipped/index.tsx | 234 +
.../domain/orders/details/order-line/edit.tsx | 299 ++
.../orders/details/order-line/index.tsx | 65 +
.../orders/details/receive-return/index.tsx | 182 +
.../domain/orders/details/refund/index.tsx | 214 +
.../domain/orders/details/returns/index.tsx | 315 ++
.../orders/details/rma-sub-modals/address.tsx | 198 +
.../details/rma-sub-modals/products.tsx | 292 ++
.../details/rma-sub-modals/return-reasons.tsx | 179 +
.../src/domain/orders/details/swap/create.tsx | 414 ++
.../orders/details/templates/address.tsx | 35 +
.../details/templates/display-total.tsx | 61 +
.../details/templates/fulfillment-status.tsx | 22 +
.../orders/details/templates/fulfillment.tsx | 129 +
.../domain/orders/details/templates/index.ts | 9 +
.../orders/details/templates/order-status.tsx | 18 +
.../details/templates/payment-actionables.tsx | 73 +
.../details/templates/payment-details.tsx | 55 +
.../details/templates/payment-status.tsx | 18 +
.../details/templates/tracking-link.tsx | 19 +
.../orders/details/utils/create-filtering.ts | 64 +
.../details/utils/get-default-values.ts | 261 +
.../details/utils/order-returnable-fields.ts | 4 +
.../utils/use-admin-expand-paramter.ts | 35 +
.../domain/orders/draft-orders/details.tsx | 510 ++
.../src/domain/orders/draft-orders/index.tsx | 69 +
.../ui/src/domain/orders/edit/context.tsx | 54 +
.../ui/src/domain/orders/edit/modal.tsx | 443 ++
.../ui/src/domain/orders/edit/utils/user.ts | 19 +
.../src/domain/orders/edit/variants-table.tsx | 303 ++
.../admin-ui/ui/src/domain/orders/index.tsx | 116 +
.../orders/new/components/billing-details.tsx | 84 +
.../new/components/custom-item-sub-modal.tsx | 85 +
.../domain/orders/new/components/items.tsx | 328 ++
.../orders/new/components/select-region.tsx | 62 +
.../orders/new/components/select-shipping.tsx | 158 +
.../new/components/shipping-details.tsx | 253 +
.../domain/orders/new/components/summary.tsx | 373 ++
.../ui/src/domain/orders/new/form/index.tsx | 211 +
.../ui/src/domain/orders/new/new-order.tsx | 135 +
.../admin-ui/ui/src/domain/orders/utils.ts | 30 +
.../src/domain/pricing/batch-job/import.tsx | 194 +
.../ui/src/domain/pricing/details/index.tsx | 42 +
.../pricing/details/sections/header.tsx | 129 +
.../edit-prices-overrides/index.tsx | 134 +
.../edit-prices-overrides/mappers.tsx | 21 +
.../product-variant-leaf.tsx | 50 +
.../sections/prices-details/edit-prices.tsx | 94 +
.../details/sections/prices-details/index.tsx | 51 +
.../prices-details/prices-table/index.tsx | 139 +
.../prices-table/use-columns.tsx | 56 +
.../details/sections/prices-details/utils.ts | 23 +
.../ui/src/domain/pricing/details/utils.ts | 11 +
.../admin-ui/ui/src/domain/pricing/index.tsx | 45 +
.../admin-ui/ui/src/domain/pricing/new.tsx | 14 +
.../pricing-form/form-header/index.tsx | 166 +
.../pricing/pricing-form/form/mappers.ts | 109 +
.../form/pricing-form-context.tsx | 168 +
.../src/domain/pricing/pricing-form/index.tsx | 43 +
.../pricing-form/sections/configuration.tsx | 201 +
.../pricing/pricing-form/sections/general.tsx | 55 +
.../pricing/pricing-form/sections/prices.tsx | 49 +
.../pricing-form/sections/product-prices.tsx | 197 +
.../pricing/pricing-form/sections/type.tsx | 51 +
.../pricing/pricing-form/types/index.ts | 104 +
.../ui/src/domain/pricing/pricing-table.tsx | 67 +
.../src/domain/products/batch-job/import.tsx | 200 +
.../components/customs-form/index.tsx | 76 +
.../components/dimensions-form/index.tsx | 75 +
.../components/discountable-form/index.tsx | 35 +
.../components/general-form/index.tsx | 103 +
.../products/components/media-form/index.tsx | 235 +
.../components/organize-form/index.tsx | 87 +
.../organize-form/use-organize-data.tsx | 35 +
.../products/components/prices-form/index.tsx | 173 +
.../components/prices-form/nested-price.tsx | 123 +
.../prices-form/price-form-input.tsx | 83 +
.../sales-channels-modal/add-screen.tsx | 132 +
.../sales-channels-modal/available-screen.tsx | 88 +
.../components/sales-channels-modal/index.tsx | 56 +
.../components/sales-channels-modal/table.tsx | 227 +
.../use-sales-channels-modal.tsx | 24 +
.../components/thumbnail-form/index.tsx | 116 +
.../create-flow-variant-form/index.tsx | 111 +
.../edit-flow-variant-form/index.tsx | 123 +
.../variant-general-form/index.tsx | 51 +
.../variant-prices-form/index.tsx | 22 +
.../variant-select-options-form/hooks.tsx | 74 +
.../variant-select-options-form/index.tsx | 78 +
.../variant-form/variant-stock-form/index.tsx | 103 +
.../edit/hooks/use-edit-product-actions.tsx | 165 +
.../ui/src/domain/products/edit/index.tsx | 70 +
.../sections/attributes/attribute-modal.tsx | 139 +
.../edit/sections/attributes/index.tsx | 68 +
.../edit/sections/general/channels-modal.tsx | 32 +
.../edit/sections/general/general-modal.tsx | 149 +
.../products/edit/sections/general/index.tsx | 169 +
.../products/edit/sections/media/index.tsx | 50 +
.../edit/sections/media/media-modal.tsx | 132 +
.../products/edit/sections/raw/index.tsx | 20 +
.../edit/sections/thumbnail/index.tsx | 82 +
.../sections/thumbnail/thumbnail-modal.tsx | 135 +
.../sections/variants/add-variant-modal.tsx | 151 +
.../sections/variants/edit-variant-modal.tsx | 154 +
.../edit-variant-screen.tsx | 146 +
.../variants/edit-variants-modal/index.tsx | 189 +
.../use-edit-variants-modal.tsx | 21 +
.../edit-variants-modal/variant-card.tsx | 170 +
.../products/edit/sections/variants/index.tsx | 180 +
.../edit/sections/variants/options-modal.tsx | 243 +
.../sections/variants/options-provider.tsx | 47 +
.../products/edit/sections/variants/table.tsx | 156 +
.../src/domain/products/filter-dropdown.tsx | 242 +
.../admin-ui/ui/src/domain/products/index.tsx | 14 +
.../products/new/add-sales-channels.tsx | 117 +
.../products/new/add-variants/index.tsx | 474 ++
.../new/add-variants/new-variant/index.tsx | 375 ++
.../ui/src/domain/products/new/index.tsx | 405 ++
.../ui/src/domain/products/overview/index.tsx | 207 +
.../src/domain/publishable-api-keys/index.tsx | 13 +
.../modals/add-sales-channels.tsx | 147 +
.../publishable-api-keys/modals/details.tsx | 103 +
.../modals/manage-sales-channels.tsx | 405 ++
.../publishable-api-keys/pages/index.tsx | 264 +
.../tables/publishable-api-keys-table.tsx | 306 ++
.../tables/sales-channels-table.tsx | 240 +
.../sales-channels/form/add-sales-channel.tsx | 203 +
.../form/edit-sales-channel.tsx | 102 +
.../ui/src/domain/sales-channels/index.tsx | 13 +
.../domain/sales-channels/pages/details.tsx | 489 ++
.../domain/sales-channels/tables/config.tsx | 56 +
.../sales-channels/tables/placeholder.tsx | 28 +
.../domain/sales-channels/tables/product.tsx | 530 ++
.../components/currency-tax-setting.tsx | 93 +
.../default-currency-selector.tsx | 96 +
.../default-store-currency/index.tsx | 26 +
.../add-currencies-screen.tsx | 146 +
.../current-currencies-screen.tsx | 175 +
.../edit-currencies-modal.tsx | 47 +
.../components/store-currencies/index.tsx | 32 +
.../components/store-currencies/table.tsx | 123 +
.../use-currency-table-columns.tsx | 58 +
.../src/domain/settings/currencies/index.tsx | 122 +
.../ui/src/domain/settings/details.tsx | 138 +
.../admin-ui/ui/src/domain/settings/index.tsx | 115 +
.../edit-user-information-modal.tsx | 109 +
.../edit-user-information/index.tsx | 65 +
.../settings/personal-information/index.tsx | 40 +
.../usage-insights/index.tsx | 55 +
.../usage-insights/usage-insights-modal.tsx | 88 +
.../region-form/region-details-form.tsx | 136 +
.../region-form/region-providers-form.tsx | 89 +
.../components/region-form/use-store-data.tsx | 58 +
.../shipping-option-card/edit-modal.tsx | 139 +
.../components/shipping-option-card/index.tsx | 113 +
.../components/shipping-option-form/index.tsx | 279 ++
.../use-shipping-option-form-data.tsx | 102 +
.../general-section/edit-region.modal.tsx | 158 +
.../regions/edit/general-section/index.tsx | 210 +
.../domain/settings/regions/edit/index.tsx | 50 +
.../create-return-shipping-option.modal.tsx | 105 +
.../edit/return-shipping-options/index.tsx | 52 +
.../create-shipping-option-modal.tsx | 105 +
.../regions/edit/shipping-options/index.tsx | 48 +
.../ui/src/domain/settings/regions/index.tsx | 25 +
.../src/domain/settings/regions/new/index.tsx | 169 +
.../regions/region-overview/index.tsx | 97 +
.../regions/region-overview/region-card.tsx | 48 +
.../return-reasons/create-reason-modal.tsx | 133 +
.../domain/settings/return-reasons/detail.tsx | 143 +
.../domain/settings/return-reasons/index.tsx | 95 +
.../ui/src/domain/settings/taxes/details.tsx | 158 +
.../src/domain/settings/taxes/edit-form.tsx | 353 ++
.../settings/taxes/edit-tax-rate-details.tsx | 76 +
.../ui/src/domain/settings/taxes/edit.tsx | 52 +
.../ui/src/domain/settings/taxes/index.tsx | 85 +
.../ui/src/domain/settings/taxes/new.tsx | 270 +
.../settings/taxes/product-selector.tsx | 77 +
.../settings/taxes/product-type-selector.tsx | 42 +
.../src/domain/settings/taxes/region-form.tsx | 167 +
.../settings/taxes/selectable-table.tsx | 193 +
.../taxes/shipping-option-selector.tsx | 44 +
.../domain/settings/taxes/tax-rate-row.tsx | 78 +
.../domain/settings/taxes/tax-rule-item.tsx | 44 +
.../settings/taxes/tax-rule-selector.tsx | 148 +
.../settings/taxes/use-tax-rate-columns.tsx | 48 +
.../ui/src/domain/settings/users/index.tsx | 85 +
.../admin-ui/ui/src/fonts/Inter-Regular.ttf | Bin 0 -> 401788 bytes
.../admin-ui/ui/src/fonts/Inter-SemiBold.ttf | Bin 0 -> 407256 bytes
.../admin-ui/ui/src/fonts/RobotoMono-Bold.ttf | Bin 0 -> 87620 bytes
.../ui/src/fonts/RobotoMono-Regular.ttf | Bin 0 -> 87520 bytes
.../ui/src/hooks/use-build-timeline.tsx | 592 +++
.../admin-ui/ui/src/hooks/use-clipboard.js | 38 +
.../ui/src/hooks/use-computed-height.ts | 19 +
.../admin-ui/ui/src/hooks/use-debounce.ts | 22 +
.../ui/src/hooks/use-detect-change.tsx | 50 +
.../ui/src/hooks/use-highlight-search.tsx | 33 +
.../ui/src/hooks/use-imperative-dialog.tsx | 139 +
packages/admin-ui/ui/src/hooks/use-is-me.tsx | 12 +
.../ui/src/hooks/use-notification.tsx | 21 +
.../ui/src/hooks/use-observe-width.ts | 30 +
.../ui/src/hooks/use-on-click-outside.tsx | 28 +
.../ui/src/hooks/use-outside-click.ts | 19 +
.../ui/src/hooks/use-query-filters.ts | 228 +
packages/admin-ui/ui/src/hooks/use-scroll.ts | 20 +
.../ui/src/hooks/use-selection-column.tsx | 39 +
.../ui/src/hooks/use-set-search-params.tsx | 24 +
.../admin-ui/ui/src/hooks/use-toggle-state.ts | 46 +
.../ui/src/hooks/use-window-dimensions.ts | 25 +
packages/admin-ui/ui/src/index.css | 3 +
packages/admin-ui/ui/src/main.tsx | 13 +
packages/admin-ui/ui/src/medusa-app.tsx | 17 +
packages/admin-ui/ui/src/pages/404.tsx | 13 +
packages/admin-ui/ui/src/pages/a.tsx | 66 +
packages/admin-ui/ui/src/pages/index.tsx | 20 +
packages/admin-ui/ui/src/pages/invite.tsx | 229 +
packages/admin-ui/ui/src/pages/login.tsx | 38 +
.../admin-ui/ui/src/pages/reset-password.tsx | 158 +
.../ui/src/providers/analytics-provider.tsx | 212 +
.../src/providers/feature-flag-provider.tsx | 73 +
.../ui/src/providers/medusa-provider.tsx | 17 +
.../ui/src/providers/polling-provider.tsx | 99 +
.../admin-ui/ui/src/providers/providers.tsx | 23 +
.../ui/src/providers/skeleton-provider.tsx | 32 +
.../admin-ui/ui/src/services/analytics.ts | 112 +
packages/admin-ui/ui/src/services/api.js | 729 +++
packages/admin-ui/ui/src/services/request.js | 15 +
.../ui/src/types/react-table-config.d.ts | 133 +
packages/admin-ui/ui/src/types/shared.ts | 55 +
packages/admin-ui/ui/src/types/utils.ts | 3 +
.../admin-ui/ui/src/utils/bytes-converter.ts | 18 +
packages/admin-ui/ui/src/utils/callAll.ts | 2 +
packages/admin-ui/ui/src/utils/color.ts | 12 +
.../ui/src/utils/consolidate-images.ts | 15 +
.../src/utils/convert-empty-string-to-null.js | 9 +
packages/admin-ui/ui/src/utils/countries.ts | 638 +++
packages/admin-ui/ui/src/utils/currencies.ts | 1087 ++++
packages/admin-ui/ui/src/utils/date-utils.ts | 5 +
.../ui/src/utils/decide-badge-color.js | 40 +
packages/admin-ui/ui/src/utils/equals-set.ts | 11 +
.../admin-ui/ui/src/utils/error-messages.ts | 10 +
.../ui/src/utils/extract-customer-name.ts | 69 +
.../admin-ui/ui/src/utils/extract-options.ts | 26 +
packages/admin-ui/ui/src/utils/filters.js | 40 +
.../admin-ui/ui/src/utils/focus-by-name.ts | 3 +
.../admin-ui/ui/src/utils/form-helpers.ts | 22 +
.../admin-ui/ui/src/utils/form-validator.ts | 67 +
.../admin-ui/ui/src/utils/format-address.js | 19 +
.../src/utils/fulfillment-providers.mapper.ts | 26 +
.../ui/src/utils/generate-promotion-code.ts | 12 +
.../admin-ui/ui/src/utils/get-combinations.js | 26 +
.../admin-ui/ui/src/utils/get-error-status.ts | 9 +
.../ui/src/utils/get-relative-time.ts | 38 +
.../ui/src/utils/handle-form-error.tsx | 65 +
packages/admin-ui/ui/src/utils/images.ts | 33 +
.../admin-ui/ui/src/utils/is-line-item.ts | 37 +
.../ui/src/utils/is-nullish-object.ts | 14 +
.../ui/src/utils/map-address-to-form.ts | 23 +
packages/admin-ui/ui/src/utils/nested-form.ts | 83 +
.../ui/src/utils/payment-providers-mapper.ts | 73 +
packages/admin-ui/ui/src/utils/prices.ts | 153 +
.../ui/src/utils/product-status-variant.ts | 13 +
.../admin-ui/ui/src/utils/remove-nullish.ts | 2 +
.../utils/sales-channel-compare-operator.ts | 15 +
packages/admin-ui/ui/src/utils/time.js | 58 +
packages/admin-ui/ui/src/utils/totals.js | 15 +
packages/admin-ui/ui/src/utils/trim-values.ts | 11 +
.../admin-ui/ui/src/utils/validate-email.ts | 7 +
.../admin-ui/ui/src/utils/xorObjFields.ts | 4 +
packages/admin-ui/ui/src/vite-env.d.ts | 3 +
packages/admin-ui/ui/tailwind.config.js | 365 ++
.../admin-ui/ui/test/fixtures/fixtures.json | 1274 +++++
packages/admin-ui/ui/test/fixtures/index.ts | 27 +
.../admin-ui/ui/test/mocks/medusa-react.tsx | 49 +
packages/admin-ui/ui/test/setup.ts | 19 +
.../ui/test/utils/render-with-providers.tsx | 27 +
packages/admin-ui/ui/tsconfig.json | 21 +
packages/admin-ui/vite.config.dev.ts | 26 +
packages/admin/.gitignore | 29 +
packages/admin/.npmignore | 2 +
packages/admin/README.md | 108 +
packages/admin/bin/medusa-admin.js | 2 +
packages/admin/package.json | 45 +
packages/admin/src/api/index.ts | 78 +
packages/admin/src/commands/build.ts | 48 +
packages/admin/src/commands/create-cli.ts | 15 +
packages/admin/src/commands/index.ts | 8 +
packages/admin/src/setup/index.ts | 84 +
packages/admin/src/types/index.ts | 36 +
packages/admin/src/utils/index.ts | 3 +
packages/admin/src/utils/load-config.ts | 32 +
packages/admin/src/utils/reporter.ts | 19 +
packages/admin/src/utils/validate-path.ts | 15 +
packages/admin/tsconfig.json | 19 +
packages/medusa-payment-paypal/package.json | 1 +
packages/medusa-react/jest.config.js | 1 -
packages/medusa-react/jest.setup.js | 26 +-
packages/medusa-react/package.json | 8 +-
.../test/hooks/admin/auth/mutations.test.ts | 4 +-
.../test/hooks/admin/auth/queries.test.ts | 4 +-
.../hooks/admin/batch-jobs/mutations.test.ts | 2 +-
.../hooks/admin/batch-jobs/queries.test.ts | 2 +-
.../test/hooks/admin/claims/mutations.test.ts | 10 +-
.../hooks/admin/collections/mutations.test.ts | 18 +-
.../hooks/admin/collections/queries.test.ts | 4 +-
.../hooks/admin/currencies/mutation.test.ts | 2 +-
.../hooks/admin/currencies/queries.test.ts | 2 +-
.../admin/customer-groups/mutations.test.ts | 4 +-
.../admin/customer-groups/queries.test.ts | 4 +-
.../hooks/admin/customers/mutations.test.ts | 4 +-
.../hooks/admin/customers/queries.test.ts | 4 +-
.../hooks/admin/discounts/mutations.test.ts | 2 +-
.../hooks/admin/discounts/queries.test.ts | 2 +-
.../admin/draft-orders/mutations.test.ts | 2 +-
.../hooks/admin/draft-orders/queries.test.ts | 4 +-
.../hooks/admin/gift-cards/mutations.test.ts | 6 +-
.../hooks/admin/gift-cards/queries.test.ts | 4 +-
.../admin/inventory-items/mutations.test.ts | 10 +-
.../admin/inventory-items/queries.test.ts | 5 +-
.../hooks/admin/invites/mutations.test.ts | 2 +-
.../test/hooks/admin/invites/queries.test.ts | 4 +-
.../test/hooks/admin/notes/mutations.test.ts | 6 +-
.../test/hooks/admin/notes/queries.test.ts | 4 +-
.../admin/notifications/mutations.test.ts | 4 +-
.../hooks/admin/notifications/queries.test.ts | 2 +-
.../hooks/admin/order-edits/mutations.test.ts | 8 +-
.../hooks/admin/order-edits/queries.test.ts | 2 +-
.../test/hooks/admin/orders/mutations.test.ts | 18 +-
.../test/hooks/admin/orders/queries.test.ts | 4 +-
.../payment-collections/mutations.test.ts | 4 +-
.../admin/payment-collections/queries.test.ts | 4 +-
.../hooks/admin/payments/mutations.test.ts | 4 +-
.../test/hooks/admin/payments/queries.test.ts | 4 +-
.../hooks/admin/price-lists/mutations.test.ts | 46 +-
.../hooks/admin/price-lists/queries.test.ts | 4 +-
.../product-categories/mutations.test.ts | 4 +-
.../admin/product-categories/queries.test.ts | 7 +-
.../hooks/admin/products/mutations.test.ts | 8 +-
.../test/hooks/admin/products/queries.test.ts | 5 +-
.../publishable-api-keys/mutations.test.ts | 10 +-
.../publishable-api-keys/queries.test.ts | 4 +-
.../hooks/admin/regions/mutations.test.ts | 8 +-
.../test/hooks/admin/regions/queries.test.ts | 6 +-
.../admin/reservations/mutations.test.ts | 9 +-
.../hooks/admin/reservations/queries.test.ts | 4 +-
.../admin/return-reasons/mutations.test.ts | 6 +-
.../admin/return-reasons/queries.test.ts | 4 +-
.../hooks/admin/returns/mutations.test.ts | 2 +-
.../test/hooks/admin/returns/queries.test.ts | 2 +-
.../admin/sales-channels/mutations.test.ts | 10 +-
.../admin/sales-channels/queries.test.ts | 4 +-
.../admin/shipping-options/mutations.test.ts | 6 +-
.../admin/shipping-options/queries.test.ts | 4 +-
.../admin/shipping-profiles/mutations.test.ts | 6 +-
.../admin/shipping-profiles/queries.test.ts | 4 +-
.../admin/stock-location/mutations.test.ts | 2 +-
.../admin/stock-location/queries.test.ts | 2 +-
.../test/hooks/admin/store/mutations.test.ts | 6 +-
.../test/hooks/admin/store/queries.test.ts | 4 +-
.../test/hooks/admin/swaps/mutations.test.ts | 4 +-
.../test/hooks/admin/swaps/queries.test.ts | 4 +-
.../hooks/admin/uploads/mutations.test.ts | 4 +-
.../test/hooks/admin/users/mutations.test.ts | 6 +-
.../test/hooks/admin/users/queries.test.ts | 4 +-
.../hooks/admin/variants/mutations.test.ts | 6 +-
.../test/hooks/admin/variants/queries.test.ts | 4 +-
.../test/hooks/store/carts/mutations.test.ts | 14 +-
.../test/hooks/store/carts/queries.test.ts | 4 +-
.../hooks/store/collections/queries.test.ts | 4 +-
.../hooks/store/customers/mutations.test.ts | 4 +-
.../hooks/store/customers/queries.test.ts | 6 +-
.../hooks/store/gift_cards/queries.test.ts | 4 +-
.../hooks/store/line-items/mutations.test.ts | 6 +-
.../hooks/store/order-edits/mutations.test.ts | 2 +-
.../hooks/store/order-edits/queries.test.ts | 4 +-
.../test/hooks/store/orders/mutations.test.ts | 4 +-
.../test/hooks/store/orders/queries.test.ts | 6 +-
.../payment-collections/mutations.test.ts | 6 +-
.../store/payment-collections/queries.test.ts | 4 +-
.../hooks/store/product-tags/queries.test.ts | 2 +-
.../test/hooks/store/products/queries.test.ts | 6 +-
.../test/hooks/store/regions/queries.test.ts | 4 +-
.../store/return-reasons/queries.test.ts | 4 +-
.../hooks/store/returns/mutations.test.ts | 4 +-
.../store/shipping-options/queries.test.ts | 6 +-
.../test/hooks/store/swaps/mutations.test.ts | 4 +-
.../test/hooks/store/swaps/queries.test.ts | 4 +-
packages/medusa-react/tsup.config.ts | 2 +
packages/medusa-source-shopify/package.json | 2 +-
packages/medusa/src/loaders/plugins.ts | 30 +-
yarn.lock | 4438 ++++++++++++++++-
928 files changed, 85430 insertions(+), 373 deletions(-)
create mode 100644 .changeset/sixty-jeans-fold.md
create mode 100644 packages/admin-ui/.gitignore
create mode 100644 packages/admin-ui/.npmignore
create mode 100644 packages/admin-ui/README.md
create mode 100644 packages/admin-ui/package.json
create mode 100644 packages/admin-ui/src/index.ts
create mode 100644 packages/admin-ui/src/types/build.ts
create mode 100644 packages/admin-ui/src/types/config.ts
create mode 100644 packages/admin-ui/src/types/index.ts
create mode 100644 packages/admin-ui/src/types/misc.ts
create mode 100644 packages/admin-ui/src/utils/format-base.ts
create mode 100644 packages/admin-ui/src/utils/get-custom-vite-config.ts
create mode 100644 packages/admin-ui/src/utils/index.ts
create mode 100644 packages/admin-ui/tsconfig.json
create mode 100644 packages/admin-ui/ui/index.html
create mode 100644 packages/admin-ui/ui/postcss.config.js
create mode 100644 packages/admin-ui/ui/public/logo.svg
create mode 100644 packages/admin-ui/ui/src/App.tsx
create mode 100644 packages/admin-ui/ui/src/assets/styles/emoji-picker.css
create mode 100644 packages/admin-ui/ui/src/assets/styles/global.css
create mode 100644 packages/admin-ui/ui/src/assets/svg/carrot.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/controller.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/flag.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/happy.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/heart.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/lightbulb.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/plane.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/search.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/sprout.svg
create mode 100644 packages/admin-ui/ui/src/assets/svg/star.svg
create mode 100644 packages/admin-ui/ui/src/components/atoms/avatar/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/back-button/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/checkbox/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/copy-to-clipboard/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/date-picker/custom-header.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/date-picker/date-picker.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/date-picker/time-picker.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/date-picker/types.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/date-picker/utils.ts
create mode 100644 packages/admin-ui/ui/src/components/atoms/fade-wrapper/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/file-upload-field/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/includes-tax-tooltip/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/input-error/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/loading-container/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/notification/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/number-scroller/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/os-shortcut/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/page-description/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/save-notification/error-state.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/save-notification/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/save-notification/saving-state.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/save-notification/success-state.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/settings-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/skeleton/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/spinner.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/switch/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/text-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/thumbnail/index.ts
create mode 100644 packages/admin-ui/ui/src/components/atoms/thumbnail/thumbnail.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/toaster-container/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/atoms/two-step-delete/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/declarative-toaster/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/badge/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/button/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/details-icon/contact.svg
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/details-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/feature-toggle.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icon-badge/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/alert-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/arrow-down-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/arrow-left-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/arrow-right-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/arrow-top-right-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/arrow-up-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/back-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/backspace-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/bell-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/bell-noti-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/bell-off-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/buildings-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/cancel-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/cart-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/cash-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/channels-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-fill-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/check-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/chevron-down.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/chevron-left-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/chevron-right-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/chevron-up.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/clipboard-copy-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/clock-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/coins-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/corner-down-right-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/cross-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/crosshair-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/customer-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/details-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/discord-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/dollar-sign-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/down-left/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/download-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/duplicate-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/export-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/eye-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/eye-off-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/fast-delivery-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/file-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/gear-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/gift-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/grip-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/happy-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/help-circle.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/image-placeholder-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/info-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/key-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/list-arrow-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/list-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/lock-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/log-out-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/long-arrow-right-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/mail-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/map-pin-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/medusa-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/medusa-vice/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/minus-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/more-horizontal-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/package-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/percent-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/plus-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/pointer-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/publish-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/refresh-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/refund.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/sad-face-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/sale-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/search-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/send-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/sided-mouth-face/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/sorting-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/sparkles-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/stop-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/tag-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/taxes-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/tile-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/trash-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/triangle-right-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/truck-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/types/icon-type.ts
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/u-turn-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/unpublish-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/upload-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/users-icon/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/warning-circle.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/icons/x-circle-icon.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/image-placeholder.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/input-container.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/input-header.tsx
create mode 100644 packages/admin-ui/ui/src/components/fundamentals/status-indicator/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/actionables.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/activity-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/amount-input/amount-and-currency-input.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/amount-input/amount-input.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/amount-input/index.ts
create mode 100644 packages/admin-ui/ui/src/components/molecules/availability-duration/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/banner-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/breadcrumb/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/collapsible-tree/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/connected-form.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/customer-avatar-item/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/customers-groups-summary/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/emoji-picker/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/filter-dropdown/container.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/filter-dropdown/item.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/filter-dropdown/save-field.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/filter-tab/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/form-error-toaster/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/form-toaster/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/generating-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/grid-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/hot-key-action/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/icon-tooltip/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/indeterminate-checkbox/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/input-signin/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/json-view/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/modal/focus-modal.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/modal/layered-modal.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/modal/side-modal.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/modal/stepped-modal.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/native-select/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/note-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/notification-bell/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/numbered-item/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/order-status/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/rma-select-shipping/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/sales-channels-display/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/sales-channels-list/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/sales-channels-summary/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/search-bar.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/section/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/containers.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/control.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/index.ts
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/input.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/menu.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/multi-value.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/placeholder.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/select-primitives.ts
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/components/single-value.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/createable-select/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/module-augmentation.ts
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/select/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/use-select-props.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/next-select/utils.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/select/select-components.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/shipping-option/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/sidebar-company-logo/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/sidebar-menu-item/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/sidebar-team-member/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/status-selector/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/switchable-item/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/table-fileds-filter/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/table-pagination/index.ts
create mode 100644 packages/admin-ui/ui/src/components/molecules/table-pagination/table-pagination.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/table-toaster/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/table/filtering-option.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/table/table-search.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/tag-grid.tsx/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/tag-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/textarea/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/claim-event/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/event-actionables.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/event-container.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/event-item-container.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/event-type.ts
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/exchange.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/items-fulfilled.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/items-shipped.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/note.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/notification/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/notification/resend-modal.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-canceled.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/canceled.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/confirmed.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/created.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/declined.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/payment-required.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/refund-required.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-edit/requested.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/order-placed.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/refund.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/timeline-events/return.tsx
create mode 100644 packages/admin-ui/ui/src/components/molecules/user-menu/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/accordion/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/activity-drawer/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/add-denomination-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/add-denomination-modal/use-values-field-array.ts
create mode 100644 packages/admin-ui/ui/src/components/organisms/analytics-config-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/analytics-preferences/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/batch-jobs-activity-list/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/batch-jobs-activity-list/utils.ts
create mode 100644 packages/admin-ui/ui/src/components/organisms/body-card.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/confirmation-prompt.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/currency-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/custom-table-header/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/delete-prompt.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/details-collapsible/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/edit-denominations-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/edit-user-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/error-boundary/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/export-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/file-upload-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/gift-card-banner/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/help-dialog/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/invite-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/login-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/medusa-price-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/metadata/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/price-input/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/product-variant-tree/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/radio-group/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/raw-json/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/reset-token-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/rma-return-product-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/rma-select-product-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/section/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/sidebar/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/table-container/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/table-container/pagination.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/table-container/types.ts
create mode 100644 packages/admin-ui/ui/src/components/organisms/timeline/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/topbar/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/organisms/upload-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/private-route/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/seo/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/add-products-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/add-products-modal/product-table-config.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/add-products-modal/utils.ts
create mode 100644 packages/admin-ui/ui/src/components/templates/address-form.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/add-product-table.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/types.ts
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/use-collection-product-columns.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/use-sorting-options.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/use-view-product-columns.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/utils.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collection-product-table/view-products-table.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collections-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collections-table/use-collection-actions.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/collections-table/use-collection-column.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-group-table/config.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-group-table/customer-groups-table.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-group-table/customers-list-table.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-group-table/edit-customers-table.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-orders-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-orders-table/use-customer-orders-columns.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-table/use-customer-columns.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/customer-table/use-customer-filters.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/discount-filter-dropdown/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/discount-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/discount-table/use-copy-promotion.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/discount-table/use-promotion-columns.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/discount-table/use-promotion-filters.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/discount-table/use-promotion-row-actions.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/draft-order-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/draft-order-table/use-draft-order-column.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/draft-order-table/use-draft-order-filters.ts
create mode 100644 packages/admin-ui/ui/src/components/templates/gift-card-filter-dropdown/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/gift-card-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/gift-card-table/use-gift-card-column.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/gift-card-table/use-gift-card-filters.ts
create mode 100644 packages/admin-ui/ui/src/components/templates/image-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/layout.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/login-layout.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/order-filter-dropdown/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/order-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/order-table/use-order-column.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/order-table/use-order-filters.ts
create mode 100644 packages/admin-ui/ui/src/components/templates/price-list-table/price-list-filters.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-list-table/price-list-table.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-list-table/use-copy-price-list.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-list-table/use-price-list-actions.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-list-table/use-price-list-columns.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-list-table/use-price-list-filters.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-list-table/utils.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-overrides/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/price-overrides/price-amount.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/product-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/product-table/overview.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/product-table/use-copy-product.ts
create mode 100644 packages/admin-ui/ui/src/components/templates/product-table/use-filter-tabs.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/product-table/use-product-actions.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/product-table/use-product-column.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/product-table/use-product-filters.ts
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/keyboard-shortcuts.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/results/customer-results.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/results/discount-results.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/results/order-results.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/results/product-results.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/section-collapsible.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/search-modal/use-keyboard-navigation-list.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/selectable-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/settings-overview.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/transfer-orders-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/two-split-pane.tsx
create mode 100644 packages/admin-ui/ui/src/components/templates/user-table.tsx
create mode 100644 packages/admin-ui/ui/src/constants/analytics.ts
create mode 100644 packages/admin-ui/ui/src/constants/medusa-backend-url.ts
create mode 100644 packages/admin-ui/ui/src/constants/query-client.ts
create mode 100644 packages/admin-ui/ui/src/domain/collections/details/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/collections/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/details/edit.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/details/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/groups/context/customer-group-context.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/groups/customer-group-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/groups/details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/groups/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/header.tsx
create mode 100644 packages/admin-ui/ui/src/domain/customers/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/add-condition/conditions-provider.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/add-condition/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/collections/add-collections.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/collections/collections-conditions-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/customer-groups/add-customer-groups.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/customer-groups/customer-groups-conditions-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/product-types/add-types.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/product-types/type-conditions-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/products/add-products.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/products/product-conditions-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/tags/add-tags.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-condition-resources/tags/tags-conditions-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/add-conditions-screens.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/condition-table-actions.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/edit-condition-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/edit-condition/edit-condition-provider.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/conditions/use-discount-conditions.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/configurations/edit-configurations.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/configurations/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/configurations/use-discount-configurations.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/general/edit-general.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/general/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/details/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/add-conditions-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/add-condition-tables/add-condition-footer.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/add-condition-tables/collections.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/add-condition-tables/customer-groups.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/add-condition-tables/products.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/add-condition-tables/tags.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/add-condition-tables/types.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/details-condition-tables/collections.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/details-condition-tables/customer-groups.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/details-condition-tables/details-condition-footer.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/details-condition-tables/products.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/details-condition-tables/tags.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/details-condition-tables/types.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/edit-condition-tables/collections.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/edit-condition-tables/customer-groups.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/edit-condition-tables/edit-condition-footer.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/edit-condition-tables/products.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/edit-condition-tables/tags.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/edit-condition-tables/types.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/shared/collection.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/shared/common.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/shared/condition-operator.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/shared/groups.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/shared/products.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/shared/tags.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/condition-tables/shared/types.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/edit-conditions-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/form/discount-form-context.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/form/mappers.ts
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/form/use-form-actions.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/sections/conditions/condition-item.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/sections/conditions/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/sections/configuration.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/sections/discount-allocation.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/sections/discount-type.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/sections/general.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/discount-form/use-condition-modal-items.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/new/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/discounts/types.ts
create mode 100644 packages/admin-ui/ui/src/domain/discounts/utils/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/custom-giftcard.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/details/edit-gift-card-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/details/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/details/update-balance-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/denomination-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/form/gift-card-form-context.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/form/mappers.ts
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/sections/denominations.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/sections/images.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/sections/information.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/manage/utils/types.ts
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/new.tsx
create mode 100644 packages/admin-ui/ui/src/domain/gift-cards/overview.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/header.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/inventory/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/components/address-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/components/edit-sales-channels/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/components/general-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/components/location-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/components/sales-channels-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/components/sales-channels-section/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/edit/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/inventory/locations/new/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/oauth/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/claim-type-form/__tests__/claim-type-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/claim-type-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-receive-form/__tests__/items-to-receive-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-receive-form/index.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-receive-form/items-to-receive-form.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-receive-form/items-to-receive-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-receive-form/use-items-to-receive-columns.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-return-form/__tests__/items-to-return-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-return-form/add-return-reason/add-return-reason-screen.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-return-form/add-return-reason/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-return-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-return-form/items-to-return-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-return-form/use-return-item-columns.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/__tests__/items-to-send-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/add-additional-items-screen/add-additional-items-screen.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/add-additional-items-screen/add-additional-items-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/add-additional-items-screen/index.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/add-additional-items-screen/use-add-additional-items-columns.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/additional-items-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/items-to-send-form/use-additional-items-columns.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/refund-amount-form/__tests__/refund-amount-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/refund-amount-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/rma-summaries/__tests__/claim-summary.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/rma-summaries/claim-summary.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/rma-summaries/index.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/rma-summaries/receive-return-summary.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/rma-summaries/summary-line-item.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/rma-summaries/summary-shipping-line.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/send-notification-form/__tests__/send-notification-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/send-notification-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/shipping-address-form/__tests__/shipping-address-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/shipping-address-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/shipping-address-form/shipping-address-form-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/shipping-form/__tests__/shipping-form.test.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/shipping-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/components/table-quantity-selector.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/address-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/claim/register-claim-menu.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/create-fulfillment/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/create-fulfillment/item-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/email-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/mark-shipped/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/order-line/edit.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/order-line/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/receive-return/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/refund/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/returns/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/rma-sub-modals/address.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/rma-sub-modals/products.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/rma-sub-modals/return-reasons.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/swap/create.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/address.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/display-total.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/fulfillment-status.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/fulfillment.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/index.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/order-status.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/payment-actionables.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/payment-details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/payment-status.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/templates/tracking-link.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/utils/create-filtering.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/utils/get-default-values.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/utils/order-returnable-fields.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/details/utils/use-admin-expand-paramter.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/draft-orders/details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/draft-orders/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/edit/context.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/edit/modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/edit/utils/user.ts
create mode 100644 packages/admin-ui/ui/src/domain/orders/edit/variants-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/components/billing-details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/components/custom-item-sub-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/components/items.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/components/select-region.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/components/select-shipping.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/components/shipping-details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/components/summary.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/new/new-order.tsx
create mode 100644 packages/admin-ui/ui/src/domain/orders/utils.ts
create mode 100644 packages/admin-ui/ui/src/domain/pricing/batch-job/import.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/header.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/edit-prices-overrides/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/edit-prices-overrides/mappers.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/edit-prices-overrides/product-variant-leaf.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/edit-prices.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/prices-table/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/prices-table/use-columns.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/sections/prices-details/utils.ts
create mode 100644 packages/admin-ui/ui/src/domain/pricing/details/utils.ts
create mode 100644 packages/admin-ui/ui/src/domain/pricing/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/new.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/form-header/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/form/mappers.ts
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/form/pricing-form-context.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/sections/configuration.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/sections/general.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/sections/prices.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/sections/product-prices.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/sections/type.tsx
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-form/types/index.ts
create mode 100644 packages/admin-ui/ui/src/domain/pricing/pricing-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/batch-job/import.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/customs-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/dimensions-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/discountable-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/general-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/media-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/organize-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/organize-form/use-organize-data.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/prices-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/prices-form/nested-price.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/prices-form/price-form-input.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/sales-channels-modal/add-screen.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/sales-channels-modal/available-screen.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/sales-channels-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/sales-channels-modal/table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/sales-channels-modal/use-sales-channels-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/thumbnail-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/variant-form/create-flow-variant-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/variant-form/edit-flow-variant-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/variant-form/variant-general-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/variant-form/variant-prices-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/variant-form/variant-select-options-form/hooks.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/variant-form/variant-select-options-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/components/variant-form/variant-stock-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/hooks/use-edit-product-actions.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/attributes/attribute-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/attributes/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/general/channels-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/general/general-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/general/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/media/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/media/media-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/raw/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/thumbnail/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/thumbnail/thumbnail-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/add-variant-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/edit-variant-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/edit-variants-modal/edit-variant-screen.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/edit-variants-modal/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/edit-variants-modal/use-edit-variants-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/edit-variants-modal/variant-card.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/options-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/options-provider.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/edit/sections/variants/table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/filter-dropdown.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/new/add-sales-channels.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/new/add-variants/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/new/add-variants/new-variant/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/new/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/products/overview/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/publishable-api-keys/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/publishable-api-keys/modals/add-sales-channels.tsx
create mode 100644 packages/admin-ui/ui/src/domain/publishable-api-keys/modals/details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/publishable-api-keys/modals/manage-sales-channels.tsx
create mode 100644 packages/admin-ui/ui/src/domain/publishable-api-keys/pages/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/publishable-api-keys/tables/publishable-api-keys-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/publishable-api-keys/tables/sales-channels-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/sales-channels/form/add-sales-channel.tsx
create mode 100644 packages/admin-ui/ui/src/domain/sales-channels/form/edit-sales-channel.tsx
create mode 100644 packages/admin-ui/ui/src/domain/sales-channels/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/sales-channels/pages/details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/sales-channels/tables/config.tsx
create mode 100644 packages/admin-ui/ui/src/domain/sales-channels/tables/placeholder.tsx
create mode 100644 packages/admin-ui/ui/src/domain/sales-channels/tables/product.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/currency-tax-setting.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/default-store-currency/default-currency-selector.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/default-store-currency/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/store-currencies/add-currencies-screen.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/store-currencies/current-currencies-screen.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/store-currencies/edit-currencies-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/store-currencies/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/store-currencies/table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/components/store-currencies/use-currency-table-columns.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/currencies/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/personal-information/edit-user-information/edit-user-information-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/personal-information/edit-user-information/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/personal-information/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/personal-information/usage-insights/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/personal-information/usage-insights/usage-insights-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/components/region-form/region-details-form.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/components/region-form/region-providers-form.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/components/region-form/use-store-data.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/components/shipping-option-card/edit-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/components/shipping-option-card/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/components/shipping-option-form/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/components/shipping-option-form/use-shipping-option-form-data.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/edit/general-section/edit-region.modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/edit/general-section/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/edit/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/edit/return-shipping-options/create-return-shipping-option.modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/edit/return-shipping-options/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/edit/shipping-options/create-shipping-option-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/edit/shipping-options/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/new/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/region-overview/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/regions/region-overview/region-card.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/return-reasons/create-reason-modal.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/return-reasons/detail.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/return-reasons/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/edit-form.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/edit-tax-rate-details.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/edit.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/index.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/new.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/product-selector.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/product-type-selector.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/region-form.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/selectable-table.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/shipping-option-selector.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/tax-rate-row.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/tax-rule-item.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/tax-rule-selector.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/taxes/use-tax-rate-columns.tsx
create mode 100644 packages/admin-ui/ui/src/domain/settings/users/index.tsx
create mode 100644 packages/admin-ui/ui/src/fonts/Inter-Regular.ttf
create mode 100644 packages/admin-ui/ui/src/fonts/Inter-SemiBold.ttf
create mode 100644 packages/admin-ui/ui/src/fonts/RobotoMono-Bold.ttf
create mode 100644 packages/admin-ui/ui/src/fonts/RobotoMono-Regular.ttf
create mode 100644 packages/admin-ui/ui/src/hooks/use-build-timeline.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-clipboard.js
create mode 100644 packages/admin-ui/ui/src/hooks/use-computed-height.ts
create mode 100644 packages/admin-ui/ui/src/hooks/use-debounce.ts
create mode 100644 packages/admin-ui/ui/src/hooks/use-detect-change.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-highlight-search.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-imperative-dialog.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-is-me.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-notification.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-observe-width.ts
create mode 100644 packages/admin-ui/ui/src/hooks/use-on-click-outside.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-outside-click.ts
create mode 100644 packages/admin-ui/ui/src/hooks/use-query-filters.ts
create mode 100644 packages/admin-ui/ui/src/hooks/use-scroll.ts
create mode 100644 packages/admin-ui/ui/src/hooks/use-selection-column.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-set-search-params.tsx
create mode 100644 packages/admin-ui/ui/src/hooks/use-toggle-state.ts
create mode 100644 packages/admin-ui/ui/src/hooks/use-window-dimensions.ts
create mode 100644 packages/admin-ui/ui/src/index.css
create mode 100644 packages/admin-ui/ui/src/main.tsx
create mode 100644 packages/admin-ui/ui/src/medusa-app.tsx
create mode 100644 packages/admin-ui/ui/src/pages/404.tsx
create mode 100644 packages/admin-ui/ui/src/pages/a.tsx
create mode 100644 packages/admin-ui/ui/src/pages/index.tsx
create mode 100644 packages/admin-ui/ui/src/pages/invite.tsx
create mode 100644 packages/admin-ui/ui/src/pages/login.tsx
create mode 100644 packages/admin-ui/ui/src/pages/reset-password.tsx
create mode 100644 packages/admin-ui/ui/src/providers/analytics-provider.tsx
create mode 100644 packages/admin-ui/ui/src/providers/feature-flag-provider.tsx
create mode 100644 packages/admin-ui/ui/src/providers/medusa-provider.tsx
create mode 100644 packages/admin-ui/ui/src/providers/polling-provider.tsx
create mode 100644 packages/admin-ui/ui/src/providers/providers.tsx
create mode 100644 packages/admin-ui/ui/src/providers/skeleton-provider.tsx
create mode 100644 packages/admin-ui/ui/src/services/analytics.ts
create mode 100644 packages/admin-ui/ui/src/services/api.js
create mode 100644 packages/admin-ui/ui/src/services/request.js
create mode 100644 packages/admin-ui/ui/src/types/react-table-config.d.ts
create mode 100644 packages/admin-ui/ui/src/types/shared.ts
create mode 100644 packages/admin-ui/ui/src/types/utils.ts
create mode 100644 packages/admin-ui/ui/src/utils/bytes-converter.ts
create mode 100644 packages/admin-ui/ui/src/utils/callAll.ts
create mode 100644 packages/admin-ui/ui/src/utils/color.ts
create mode 100644 packages/admin-ui/ui/src/utils/consolidate-images.ts
create mode 100644 packages/admin-ui/ui/src/utils/convert-empty-string-to-null.js
create mode 100644 packages/admin-ui/ui/src/utils/countries.ts
create mode 100644 packages/admin-ui/ui/src/utils/currencies.ts
create mode 100644 packages/admin-ui/ui/src/utils/date-utils.ts
create mode 100644 packages/admin-ui/ui/src/utils/decide-badge-color.js
create mode 100644 packages/admin-ui/ui/src/utils/equals-set.ts
create mode 100644 packages/admin-ui/ui/src/utils/error-messages.ts
create mode 100644 packages/admin-ui/ui/src/utils/extract-customer-name.ts
create mode 100644 packages/admin-ui/ui/src/utils/extract-options.ts
create mode 100644 packages/admin-ui/ui/src/utils/filters.js
create mode 100644 packages/admin-ui/ui/src/utils/focus-by-name.ts
create mode 100644 packages/admin-ui/ui/src/utils/form-helpers.ts
create mode 100644 packages/admin-ui/ui/src/utils/form-validator.ts
create mode 100644 packages/admin-ui/ui/src/utils/format-address.js
create mode 100644 packages/admin-ui/ui/src/utils/fulfillment-providers.mapper.ts
create mode 100644 packages/admin-ui/ui/src/utils/generate-promotion-code.ts
create mode 100644 packages/admin-ui/ui/src/utils/get-combinations.js
create mode 100644 packages/admin-ui/ui/src/utils/get-error-status.ts
create mode 100644 packages/admin-ui/ui/src/utils/get-relative-time.ts
create mode 100644 packages/admin-ui/ui/src/utils/handle-form-error.tsx
create mode 100644 packages/admin-ui/ui/src/utils/images.ts
create mode 100644 packages/admin-ui/ui/src/utils/is-line-item.ts
create mode 100644 packages/admin-ui/ui/src/utils/is-nullish-object.ts
create mode 100644 packages/admin-ui/ui/src/utils/map-address-to-form.ts
create mode 100644 packages/admin-ui/ui/src/utils/nested-form.ts
create mode 100644 packages/admin-ui/ui/src/utils/payment-providers-mapper.ts
create mode 100644 packages/admin-ui/ui/src/utils/prices.ts
create mode 100644 packages/admin-ui/ui/src/utils/product-status-variant.ts
create mode 100644 packages/admin-ui/ui/src/utils/remove-nullish.ts
create mode 100644 packages/admin-ui/ui/src/utils/sales-channel-compare-operator.ts
create mode 100644 packages/admin-ui/ui/src/utils/time.js
create mode 100644 packages/admin-ui/ui/src/utils/totals.js
create mode 100644 packages/admin-ui/ui/src/utils/trim-values.ts
create mode 100644 packages/admin-ui/ui/src/utils/validate-email.ts
create mode 100644 packages/admin-ui/ui/src/utils/xorObjFields.ts
create mode 100644 packages/admin-ui/ui/src/vite-env.d.ts
create mode 100644 packages/admin-ui/ui/tailwind.config.js
create mode 100644 packages/admin-ui/ui/test/fixtures/fixtures.json
create mode 100644 packages/admin-ui/ui/test/fixtures/index.ts
create mode 100644 packages/admin-ui/ui/test/mocks/medusa-react.tsx
create mode 100644 packages/admin-ui/ui/test/setup.ts
create mode 100644 packages/admin-ui/ui/test/utils/render-with-providers.tsx
create mode 100644 packages/admin-ui/ui/tsconfig.json
create mode 100644 packages/admin-ui/vite.config.dev.ts
create mode 100644 packages/admin/.gitignore
create mode 100644 packages/admin/.npmignore
create mode 100644 packages/admin/README.md
create mode 100755 packages/admin/bin/medusa-admin.js
create mode 100644 packages/admin/package.json
create mode 100644 packages/admin/src/api/index.ts
create mode 100644 packages/admin/src/commands/build.ts
create mode 100644 packages/admin/src/commands/create-cli.ts
create mode 100644 packages/admin/src/commands/index.ts
create mode 100644 packages/admin/src/setup/index.ts
create mode 100644 packages/admin/src/types/index.ts
create mode 100644 packages/admin/src/utils/index.ts
create mode 100644 packages/admin/src/utils/load-config.ts
create mode 100644 packages/admin/src/utils/reporter.ts
create mode 100644 packages/admin/src/utils/validate-path.ts
create mode 100644 packages/admin/tsconfig.json
diff --git a/.changeset/sixty-jeans-fold.md b/.changeset/sixty-jeans-fold.md
new file mode 100644
index 0000000000000..fad382fbe9eb9
--- /dev/null
+++ b/.changeset/sixty-jeans-fold.md
@@ -0,0 +1,7 @@
+---
+"@medusajs/admin-ui": patch
+"@medusajs/medusa": patch
+"@medusajs/admin": patch
+---
+
+feat(medusa,admin,admin-ui): Add new plugin to serve the admin dashboard from the server. Adds a new plugin injection step `setup`, code placed in the `setup` folder of a plugin will be run before any code from a plugin is injected into the Medusa server.
diff --git a/.eslintignore b/.eslintignore
index 201dccdc07700..7c26663d157ed 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -7,6 +7,8 @@ jest*
packages/*
# List of packages to Lint
!packages/medusa
+!packages/admin-ui
+!packages/admin
!packages/medusa-payment-stripe
diff --git a/.eslintrc.js b/.eslintrc.js
index 9893804579d03..49f7bc6f009c9 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -83,7 +83,8 @@ module.exports = {
project: [
"./packages/medusa/tsconfig.json",
"./packages/medusa-payment-stripe/tsconfig.spec.json",
- ]
+ "./packages/admin-ui/tsconfig.json",
+ ],
},
rules: {
"valid-jsdoc": "off",
@@ -111,5 +112,58 @@ module.exports = {
"@typescript-eslint/no-var-requires": "off",
},
},
+ {
+ files: ["packages/admin-ui/ui/**/*.ts", "packages/admin-ui/ui/**/*.tsx"],
+ plugins: ["unused-imports"],
+ extends: [
+ "plugin:react/recommended",
+ "plugin:react/jsx-runtime",
+ "plugin:react-hooks/recommended",
+ ],
+ parser: "@typescript-eslint/parser",
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
+ sourceType: "module", // Allows for the use of imports
+ project: "./packages/admin-ui/ui/tsconfig.json",
+ },
+ env: {
+ browser: true,
+ },
+ rules: {
+ "prettier/prettier": "error",
+ "react/prop-types": "off",
+ "new-cap": "off",
+ "require-jsdoc": "off",
+ "valid-jsdoc": "off",
+ "no-unused-expressions": "off",
+ "unused-imports/no-unused-imports": "error",
+ "unused-imports/no-unused-vars": [
+ "warn",
+ {
+ vars: "all",
+ varsIgnorePattern: "^_",
+ args: "after-used",
+ argsIgnorePattern: "^_",
+ },
+ ],
+ },
+ },
+ {
+ files: ["packages/admin-ui/lib/**/*.ts"],
+ parser: "@typescript-eslint/parser",
+ parserOptions: {
+ project: "./packages/admin-ui/tsconfig.json",
+ },
+ },
+ {
+ files: ["packages/admin/**/*.ts"],
+ parser: "@typescript-eslint/parser",
+ parserOptions: {
+ project: "./packages/admin/tsconfig.json",
+ },
+ },
],
}
diff --git a/.prettierrc b/.prettierrc
index aa4d695476ae2..3718cf898655b 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -4,5 +4,13 @@
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
- "arrowParens": "always"
+ "arrowParens": "always",
+ "overrides": [
+ {
+ "files": "./packages/admin-ui/**/*.{js,jsx,ts,tsx}",
+ "options": {
+ "plugins": ["prettier-plugin-tailwindcss"]
+ }
+ }
+ ]
}
diff --git a/integration-tests/api/package.json b/integration-tests/api/package.json
index f2f39f27f467a..569e097737397 100644
--- a/integration-tests/api/package.json
+++ b/integration-tests/api/package.json
@@ -19,6 +19,7 @@
"@babel/core": "^7.12.10",
"@babel/node": "^7.12.10",
"babel-preset-medusa-package": "*",
- "jest": "^26.6.3"
+ "jest": "^26.6.3",
+ "jest-environment-node": "26.6.2"
}
}
diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json
index 500f22163172d..320e2a4369da6 100644
--- a/integration-tests/plugins/package.json
+++ b/integration-tests/plugins/package.json
@@ -21,6 +21,7 @@
"@babel/core": "^7.12.10",
"@babel/node": "^7.12.10",
"babel-preset-medusa-package": "*",
- "jest": "^26.6.3"
+ "jest": "^26.6.3",
+ "jest-environment-node": "26.6.2"
}
}
diff --git a/integration-tests/repositories/package.json b/integration-tests/repositories/package.json
index 846ba465e8460..c279b788a8408 100644
--- a/integration-tests/repositories/package.json
+++ b/integration-tests/repositories/package.json
@@ -17,6 +17,7 @@
"@babel/core": "^7.12.10",
"@babel/node": "^7.12.10",
"babel-preset-medusa-package": "*",
- "jest": "^26.6.3"
+ "jest": "^26.6.3",
+ "jest-environment-node": "26.6.2"
}
}
diff --git a/package.json b/package.json
index fb1b0d07161fe..a3be3300441cd 100644
--- a/package.json
+++ b/package.json
@@ -23,8 +23,8 @@
"@medusajs/medusa-oas-cli": "*",
"@readme/openapi-parser": "^2.4.0",
"@redocly/cli": "1.0.0-beta.123",
- "@typescript-eslint/eslint-plugin": "^5.36.2",
- "@typescript-eslint/parser": "^5.36.2",
+ "@typescript-eslint/eslint-plugin": "^5.53.0",
+ "@typescript-eslint/parser": "^5.53.0",
"axios": "^0.21.4",
"axios-mock-adapter": "^1.19.0",
"babel-jest": "^26.6.3",
@@ -36,6 +36,8 @@
"eslint-plugin-markdown": "^3.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.11",
+ "eslint-plugin-react-hooks": "^4.6.0",
+ "eslint-plugin-unused-imports": "^2.0.0",
"execa": "^5.1.1",
"express": "^4.17.1",
"get-port": "^5.1.1",
@@ -47,6 +49,7 @@
"microbundle": "^0.13.3",
"pg-god": "^1.0.12",
"prettier": "^2.7.1",
+ "prettier-plugin-tailwindcss": "^0.2.3",
"resolve-cwd": "^3.0.0",
"ts-jest": "^26.5.6",
"ts-node": "^10.9.1",
diff --git a/packages/admin-ui/.gitignore b/packages/admin-ui/.gitignore
new file mode 100644
index 0000000000000..cc4ef712b4658
--- /dev/null
+++ b/packages/admin-ui/.gitignore
@@ -0,0 +1,4 @@
+/dist
+/build
+.vercel
+/ui/preview
\ No newline at end of file
diff --git a/packages/admin-ui/.npmignore b/packages/admin-ui/.npmignore
new file mode 100644
index 0000000000000..2d1db95136d3e
--- /dev/null
+++ b/packages/admin-ui/.npmignore
@@ -0,0 +1,6 @@
+.DS_store
+.turbo
+/src
+/build
+.vercel
+/ui/preview
\ No newline at end of file
diff --git a/packages/admin-ui/README.md b/packages/admin-ui/README.md
new file mode 100644
index 0000000000000..71226fb350f69
--- /dev/null
+++ b/packages/admin-ui/README.md
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+ @medusajs/admin-ui
+
+
+
+
+
+An open source composable commerce engine built for developers.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## The Medusa Admin App. Included with the [`@medusajs/admin`](https://www.npmjs.com/package/@medusajs/admin) plugin. You shouldn't install this package separately.
diff --git a/packages/admin-ui/package.json b/packages/admin-ui/package.json
new file mode 100644
index 0000000000000..86f6f1deac94f
--- /dev/null
+++ b/packages/admin-ui/package.json
@@ -0,0 +1,90 @@
+{
+ "name": "@medusajs/admin-ui",
+ "author": "Kasper Kristensen ",
+ "license": "MIT",
+ "version": "0.0.0",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/medusajs/medusa.git",
+ "directory": "packages/admin-ui"
+ },
+ "exports": {
+ ".": "./dist/index.js",
+ "./ui": "./ui",
+ "./package.json": "./package.json"
+ },
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist",
+ "ui"
+ ],
+ "scripts": {
+ "dev": "vite -c vite.config.dev.ts --port 7001",
+ "build": "tsc --build",
+ "test:ui": "vitest --config vite.config.dev.ts",
+ "test:ui:once": "vitest --config vite.config.dev.ts --run",
+ "test": "echo \"Tests disabled temporarily\""
+ },
+ "dependencies": {
+ "@hookform/error-message": "^2.0.1",
+ "@radix-ui/react-accordion": "^1.0.1",
+ "@radix-ui/react-avatar": "^1.0.1",
+ "@radix-ui/react-collapsible": "^1.0.1",
+ "@radix-ui/react-dialog": "^1.0.2",
+ "@radix-ui/react-dropdown-menu": "^2.0.2",
+ "@radix-ui/react-popover": "^1.0.3",
+ "@radix-ui/react-radio-group": "^1.1.1",
+ "@radix-ui/react-select": "^1.2.0",
+ "@radix-ui/react-switch": "^1.0.1",
+ "@radix-ui/react-tooltip": "^1.0.3",
+ "@segment/analytics-next": "^1.51.1",
+ "@tanstack/react-query": "4.22.0",
+ "@tanstack/react-table": "^8.7.9",
+ "@vitejs/plugin-react": "^3.1.0",
+ "clsx": "^1.2.1",
+ "confetti-js": "^0.0.18",
+ "copy-to-clipboard": "^3.3.1",
+ "emoji-picker-react": "^4.4.3",
+ "framer-motion": "^9.1.6",
+ "medusa-react": "*",
+ "react": "^18.2.0",
+ "react-collapsible": "^2.8.3",
+ "react-country-flag": "^3.0.2",
+ "react-currency-input-field": "^3.6.8",
+ "react-datepicker": "^4.8.0",
+ "react-dnd": "^16.0.1",
+ "react-dnd-html5-backend": "^16.0.1",
+ "react-dom": "^18.2.0",
+ "react-helmet": "^6.0.0",
+ "react-highlight-words": "^0.18.0",
+ "react-hook-form": "7.38.0",
+ "react-hot-toast": "^2.4.0",
+ "react-hotkeys-hook": "^3.4.7",
+ "react-json-tree": "^0.17.0",
+ "react-jwt": "^1.1.4",
+ "react-router-dom": "^6.8.0",
+ "react-select": "^5.5.4",
+ "react-table": "^7.7.0",
+ "type-fest": "^3.6.0",
+ "vite": "^4.1.4"
+ },
+ "devDependencies": {
+ "@medusajs/medusa": "*",
+ "@tailwindcss/forms": "^0.5.3",
+ "@tailwindcss/line-clamp": "^0.4.2",
+ "@testing-library/jest-dom": "^5.16.5",
+ "@testing-library/react": "^14.0.0",
+ "@testing-library/user-event": "^14.4.3",
+ "@types/react": "^18.0.27",
+ "@types/react-dom": "^18.0.10",
+ "@types/react-table": "^7.7.9",
+ "autoprefixer": "^10.4.13",
+ "postcss": "^8.4.21",
+ "tailwindcss": "3.2.2",
+ "tailwindcss-radix": "^2.7.0",
+ "typescript": "^4.9.3",
+ "vitest": "^0.28.5"
+ },
+ "packageManager": "yarn@3.2.1"
+}
diff --git a/packages/admin-ui/src/index.ts b/packages/admin-ui/src/index.ts
new file mode 100644
index 0000000000000..39f937d08947d
--- /dev/null
+++ b/packages/admin-ui/src/index.ts
@@ -0,0 +1,28 @@
+import fse from "fs-extra"
+import { resolve } from "path"
+import vite from "vite"
+import { AdminBuildConfig } from "./types"
+import { getCustomViteConfig } from "./utils"
+
+async function build(options?: AdminBuildConfig) {
+ const config = getCustomViteConfig(options)
+
+ await vite.build(config).catch((_err) => {
+ process.exit(1)
+ })
+
+ await fse.writeJSON(
+ resolve(config.build.outDir, "build-manifest.json"),
+ options
+ )
+}
+
+async function watch() {
+ throw new Error("Not implemented")
+}
+
+async function clean() {
+ throw new Error("Not implemented")
+}
+
+export { build, watch, clean }
diff --git a/packages/admin-ui/src/types/build.ts b/packages/admin-ui/src/types/build.ts
new file mode 100644
index 0000000000000..0449a178dba65
--- /dev/null
+++ b/packages/admin-ui/src/types/build.ts
@@ -0,0 +1,15 @@
+import { DeepPartial } from "./misc"
+
+type GlobalsConfig = {
+ base?: string
+ backend?: string
+}
+
+type BuildConfig = {
+ outDir?: string
+}
+
+export type AdminBuildConfig = {
+ globals?: DeepPartial
+ build?: DeepPartial
+}
diff --git a/packages/admin-ui/src/types/config.ts b/packages/admin-ui/src/types/config.ts
new file mode 100644
index 0000000000000..8bfd6137c95d2
--- /dev/null
+++ b/packages/admin-ui/src/types/config.ts
@@ -0,0 +1,5 @@
+import { AdminBuildConfig } from "./build"
+
+export type AdminUIConfig = {
+ build?: AdminBuildConfig
+}
diff --git a/packages/admin-ui/src/types/index.ts b/packages/admin-ui/src/types/index.ts
new file mode 100644
index 0000000000000..348f635b62ca9
--- /dev/null
+++ b/packages/admin-ui/src/types/index.ts
@@ -0,0 +1,2 @@
+export * from "./build"
+export * from "./misc"
diff --git a/packages/admin-ui/src/types/misc.ts b/packages/admin-ui/src/types/misc.ts
new file mode 100644
index 0000000000000..3ab124072a3ea
--- /dev/null
+++ b/packages/admin-ui/src/types/misc.ts
@@ -0,0 +1,9 @@
+export type DeepPartial = {
+ [P in keyof T]?: T[P] extends (infer U)[]
+ ? DeepPartial[]
+ : T[P] extends ReadonlyArray
+ ? ReadonlyArray>
+ : DeepPartial
+}
+
+export type Base = `/${T}/`
diff --git a/packages/admin-ui/src/utils/format-base.ts b/packages/admin-ui/src/utils/format-base.ts
new file mode 100644
index 0000000000000..cbf2e0f14a421
--- /dev/null
+++ b/packages/admin-ui/src/utils/format-base.ts
@@ -0,0 +1,5 @@
+import { Base } from "../types"
+
+export const formatBase = (base: T): Base => {
+ return `/${base}/`
+}
diff --git a/packages/admin-ui/src/utils/get-custom-vite-config.ts b/packages/admin-ui/src/utils/get-custom-vite-config.ts
new file mode 100644
index 0000000000000..7bc4af95543ad
--- /dev/null
+++ b/packages/admin-ui/src/utils/get-custom-vite-config.ts
@@ -0,0 +1,76 @@
+import react from "@vitejs/plugin-react"
+import { resolve } from "path"
+import { BuildOptions, InlineConfig } from "vite"
+import { AdminBuildConfig } from "../types"
+import { formatBase } from "./format-base"
+
+export const getCustomViteConfig = (config: AdminBuildConfig): InlineConfig => {
+ const { globals = {}, build = {} } = config
+
+ const uiPath = resolve(__dirname, "..", "..", "ui")
+
+ const globalReplacements = () => {
+ const base = globals.base || "app"
+
+ let backend = "/"
+
+ if (globals.backend) {
+ try {
+ // Test if the backend is a valid URL
+ new URL(globals.backend)
+ backend = globals.backend
+ } catch (_e) {
+ throw new Error(
+ `The provided backend URL is not valid: ${globals.backend}. Please provide a valid URL (e.g. https://my-medusa-server.com).`
+ )
+ }
+ }
+
+ return {
+ __BASE__: JSON.stringify(`/${base}`),
+ __MEDUSA_BACKEND_URL__: JSON.stringify(backend),
+ }
+ }
+
+ const buildConfig = (): BuildOptions => {
+ const { outDir } = build
+
+ let destDir: string
+
+ if (!outDir) {
+ /**
+ * Default build directory is at the root of the `@medusajs/admin-ui` package.
+ */
+ destDir = resolve(__dirname, "..", "..", "build")
+ } else {
+ /**
+ * If a custom build directory is specified, it is resolved relative to the
+ * current working directory.
+ */
+ destDir = resolve(process.cwd(), outDir)
+ }
+
+ return {
+ outDir: destDir,
+ emptyOutDir: true,
+ }
+ }
+
+ return {
+ plugins: [react()],
+ root: uiPath,
+ mode: "production",
+ base: formatBase(globals.base),
+ define: globalReplacements(),
+ build: buildConfig(),
+ resolve: {
+ alias: {
+ "@tanstack/react-query": resolve(
+ require.resolve("@tanstack/react-query")
+ ),
+ },
+ },
+ clearScreen: false,
+ logLevel: "error",
+ }
+}
diff --git a/packages/admin-ui/src/utils/index.ts b/packages/admin-ui/src/utils/index.ts
new file mode 100644
index 0000000000000..06ac389b4cd8f
--- /dev/null
+++ b/packages/admin-ui/src/utils/index.ts
@@ -0,0 +1,2 @@
+export * from "./format-base"
+export * from "./get-custom-vite-config"
diff --git a/packages/admin-ui/tsconfig.json b/packages/admin-ui/tsconfig.json
new file mode 100644
index 0000000000000..ff0e60262a0f4
--- /dev/null
+++ b/packages/admin-ui/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "declaration": true,
+ "declarationMap": true,
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "noEmit": false,
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "outDir": "dist",
+ "rootDir": "src",
+ "skipLibCheck": true
+ },
+ "include": ["src"],
+ "exclude": ["**/node_modules", "ui"]
+}
diff --git a/packages/admin-ui/ui/index.html b/packages/admin-ui/ui/index.html
new file mode 100644
index 0000000000000..3732020477520
--- /dev/null
+++ b/packages/admin-ui/ui/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Medusa
+
+
+
+
+
+
diff --git a/packages/admin-ui/ui/postcss.config.js b/packages/admin-ui/ui/postcss.config.js
new file mode 100644
index 0000000000000..8a0deb6f9864b
--- /dev/null
+++ b/packages/admin-ui/ui/postcss.config.js
@@ -0,0 +1,9 @@
+const path = require("path")
+
+module.exports = {
+ plugins: {
+ "tailwindcss/nesting": {},
+ tailwindcss: { config: path.join(__dirname, "tailwind.config.js") },
+ autoprefixer: {},
+ },
+}
diff --git a/packages/admin-ui/ui/public/logo.svg b/packages/admin-ui/ui/public/logo.svg
new file mode 100644
index 0000000000000..87c22a658734a
--- /dev/null
+++ b/packages/admin-ui/ui/public/logo.svg
@@ -0,0 +1,10 @@
+
diff --git a/packages/admin-ui/ui/src/App.tsx b/packages/admin-ui/ui/src/App.tsx
new file mode 100644
index 0000000000000..06c7fb458599b
--- /dev/null
+++ b/packages/admin-ui/ui/src/App.tsx
@@ -0,0 +1,45 @@
+import { lazy, Suspense } from "react"
+import {
+ createBrowserRouter,
+ createRoutesFromElements,
+ Route,
+ RouterProvider,
+} from "react-router-dom"
+import Spinner from "./components/atoms/spinner"
+
+const NotFound = lazy(() => import("./pages/404"))
+const Dashboard = lazy(() => import("./pages/a"))
+const IndexPage = lazy(() => import("./pages/index"))
+const InvitePage = lazy(() => import("./pages/invite"))
+const LoginPage = lazy(() => import("./pages/login"))
+const ResetPasswordPage = lazy(() => import("./pages/reset-password"))
+
+const router = createBrowserRouter(
+ createRoutesFromElements(
+ <>
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ >
+ ),
+ {
+ basename: __BASE__,
+ }
+)
+
+const Loading = () => (
+
+
+
+)
+
+const App = () => (
+ }>
+
+
+)
+
+export default App
diff --git a/packages/admin-ui/ui/src/assets/styles/emoji-picker.css b/packages/admin-ui/ui/src/assets/styles/emoji-picker.css
new file mode 100644
index 0000000000000..59eb2c83ecbcd
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/styles/emoji-picker.css
@@ -0,0 +1,107 @@
+.emoji-picker-react {
+ padding: 16px !important;
+ border: none !important;
+}
+
+.emoji-picker-react .emoji-group {
+ padding: 0 !important;
+ font-size: 12px !important;
+ font-weight: 400 !important;
+}
+
+.emoji-picker-react .emoji-group:before {
+ font-family: "Inter" !important;
+ text-transform: none !important;
+ font-size: 12px !important;
+ font-weight: 600 !important;
+}
+
+.emoji-picker-react .native {
+ font-size: 24px !important;
+}
+
+.emoji-picker-react .emoji {
+ color: #F3F4F6 !important;
+}
+
+.emoji-picker-react input.emoji-search {
+ background-color: #F9FAFB !important;
+ border-radius: 4px !important;
+ border-color: #E5E7EB !important;
+ margin: 0 !important;
+ width: 100% !important;
+ font-size: 12px !important;
+ font-family: "Inter" !important;
+ color: #111827 !important;
+ caret-color: #7C3AED !important;
+}
+
+.emoji-picker-react input.emoji-search::placeholder {
+ font-size: 12px !important;
+ font-family: "Inter" !important;
+ color: #9CA3AF !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-smileys_people {
+ background-image: url("../svg/happy.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-animals_nature {
+ background-image: url("../svg/sprout.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-food_drink {
+ background-image: url("../svg/carrot.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-travel_places {
+ background-image: url("../svg/plane.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-activities {
+ background-image: url("../svg/controller.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-objects {
+ background-image: url("../svg/lightbulb.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-symbols {
+ background-image: url("../svg/heart.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button.icn-flags {
+ background-image: url("../svg/flag.svg") !important;
+}
+
+.emoji-picker-react .emoji-categories button {
+ width: 32px !important;
+ height: 32px !important;
+ border-radius: 4px !important;
+}
+
+.emoji-picker-react .emoji-categories button.active {
+ background-color: white !important;
+}
+
+.emoji-picker-react .emoji-categories {
+ background-color: #F3F4F6 !important;
+ padding: 4px !important;
+ border-radius: 4px !important;
+ margin-bottom: 8px !important;
+}
+
+.emoji-picker-react .active-category-indicator-wrapper .active-category-indicator {
+ display: none !important;
+}
+
+.emoji-scroll-wrapper {
+ overflow-x: hidden !important;
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
+}
+
+.emoji-scroll-wrapper::-webkit-scrollbar {
+ /* chrome */
+ display: none;
+}
\ No newline at end of file
diff --git a/packages/admin-ui/ui/src/assets/styles/global.css b/packages/admin-ui/ui/src/assets/styles/global.css
new file mode 100644
index 0000000000000..c5c679f4b797c
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/styles/global.css
@@ -0,0 +1,456 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@font-face {
+ font-family: "Inter";
+ src: url("../../fonts/Inter-Regular.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Inter";
+ src: url("../../fonts/Inter-SemiBold.ttf") format("truetype");
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Roboto Mono";
+ src: url("../../fonts/RobotoMono-Bold.ttf") format("truetype");
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Roboto Mono";
+ src: url("../../fonts/RobotoMono-Regular.ttf") format("truetype");
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@layer base {
+ html {
+ @apply overflow-hidden;
+ }
+}
+
+@layer components {
+ .inter-5xlarge-regular {
+ @apply font-sans text-5xlarge leading-4xlarge font-normal;
+ }
+ .inter-5xlarge-semibold {
+ @apply font-sans text-5xlarge leading-4xlarge font-semibold;
+ }
+
+ .inter-4xlarge-regular {
+ @apply font-sans text-4xlarge leading-3xlarge font-normal;
+ }
+ .inter-4xlarge-semibold {
+ @apply font-sans text-4xlarge leading-3xlarge font-semibold;
+ }
+
+ .inter-3xlarge-regular {
+ @apply font-sans text-3xlarge leading-2xlarge font-normal;
+ }
+ .inter-3xlarge-semibold {
+ @apply font-sans text-3xlarge leading-2xlarge font-semibold;
+ }
+
+ .inter-2xlarge-regular {
+ @apply font-sans text-2xlarge leading-xlarge font-normal;
+ }
+ .inter-2xlarge-semibold {
+ @apply font-sans text-2xlarge leading-xlarge font-semibold;
+ }
+
+ .inter-xlarge-regular {
+ @apply font-sans text-xlarge leading-large font-normal;
+ }
+ .inter-xlarge-semibold {
+ @apply font-sans text-xlarge leading-large font-semibold;
+ }
+
+ .inter-large-regular {
+ @apply font-sans text-large leading-base font-normal;
+ }
+ .inter-large-semibold {
+ @apply font-sans text-large leading-base font-semibold;
+ }
+
+ .inter-base-regular {
+ @apply font-sans text-base leading-base font-normal;
+ }
+ .inter-base-semibold {
+ @apply font-sans text-base leading-base font-semibold;
+ }
+
+ .inter-small-regular {
+ @apply font-sans text-small leading-small font-normal;
+ }
+ .inter-small-semibold {
+ @apply font-sans text-small leading-small font-semibold;
+ }
+
+ .inter-xsmall-regular {
+ @apply font-sans text-xsmall leading-xsmall font-normal;
+ }
+ .inter-xsmall-semibold {
+ @apply font-sans text-xsmall leading-xsmall font-semibold;
+ }
+
+ .mono-5xlarge-regular {
+ @apply font-mono text-5xlarge leading-4xlarge font-normal;
+ }
+ .mono-5xlarge-semibold {
+ @apply font-mono text-5xlarge leading-4xlarge font-bold;
+ }
+
+ .mono-4xlarge-regular {
+ @apply font-mono text-4xlarge leading-3xlarge font-normal;
+ }
+ .mono-4xlarge-semibold {
+ @apply font-mono text-4xlarge leading-3xlarge font-bold;
+ }
+
+ .mono-3xlarge-regular {
+ @apply font-mono text-3xlarge leading-2xlarge font-normal;
+ }
+ .mono-3xlarge-semibold {
+ @apply font-mono text-3xlarge leading-2xlarge font-bold;
+ }
+
+ .mono-2xlarge-regular {
+ @apply font-mono text-2xlarge leading-xlarge font-normal;
+ }
+ .mono-2xlarge-semibold {
+ @apply font-mono text-2xlarge leading-xlarge font-bold;
+ }
+
+ .mono-xlarge-regular {
+ @apply font-mono text-xlarge leading-large font-normal;
+ }
+ .mono-xlarge-semibold {
+ @apply font-mono text-xlarge leading-large font-bold;
+ }
+
+ .mono-large-regular {
+ @apply font-mono text-large leading-base font-normal;
+ }
+ .mono-large-semibold {
+ @apply font-mono text-large leading-base font-bold;
+ }
+
+ .mono-base-regular {
+ @apply font-mono text-base leading-base font-normal;
+ }
+ .mono-base-semibold {
+ @apply font-mono text-base leading-base font-bold;
+ }
+
+ .mono-small-regular {
+ @apply font-mono text-small leading-small font-normal;
+ }
+ .mono-small-semibold {
+ @apply font-mono text-small leading-small font-bold;
+ }
+
+ .mono-xsmall-regular {
+ @apply font-mono text-xsmall leading-xsmall font-normal;
+ }
+ .mono-xsmall-semibold {
+ @apply font-mono text-xsmall leading-xsmall font-bold;
+ }
+
+ .radio-outer-ring > span.indicator[data-state="checked"] {
+ @apply rounded-circle shadow-violet-60 shadow-[0_0_0_2px];
+ }
+
+ .bold-active-item + span {
+ @apply inter-base-semibold;
+ }
+}
+
+@layer components {
+ .react-select-container {
+ @apply p-0 -mx-3 border-0 mb-1 cursor-text h-6;
+
+ .react-select__control {
+ @apply border-0 bg-inherit shadow-none;
+ }
+
+ .react-select__control,
+ .react-select__control--is-focused,
+ .react-select__control--menu-is-open {
+ @apply h-6 p-0 m-0 !important;
+ }
+
+ .react-select__value-container--is-multi,
+ .react-select__value-container--has-value {
+ @apply h-6 pl-3 p-0 m-0 !important;
+ }
+
+ .react-select__menu,
+ .react-select__menu-list {
+ @apply rounded-t-none mt-0 z-[110] !important;
+ }
+
+ .react-select__value-container {
+ @apply pl-3 pr-0;
+ }
+
+ .react-select__indicators {
+ @apply p-0 h-full items-center flex pr-3;
+
+ .react-select__indicator {
+ @apply p-0;
+ }
+ }
+
+ .react-select__input {
+ @apply w-full mt-0 min-w-[120px] pt-0 !important;
+ }
+
+ .react-select__option,
+ .react-select__option--is-focused,
+ .react-select__option--is-selected {
+ @apply bg-grey-0 hover:bg-grey-5 !important;
+ }
+
+ .react-select__multi-value,
+ .react-select__input-container {
+ @apply my-0 py-0;
+ }
+ }
+}
+
+@layer components {
+ .badge {
+ @apply w-min py-0.5 px-2 rounded-rounded inter-small-semibold;
+ }
+
+ .badge-disabled {
+ @apply bg-grey-50 bg-opacity-10 text-grey-50;
+ }
+
+ .badge-primary {
+ @apply bg-violet-60 bg-opacity-10 text-violet-60;
+ }
+
+ .badge-danger {
+ @apply bg-rose-50 bg-opacity-10 text-rose-50;
+ }
+
+ .badge-success {
+ @apply bg-teal-50 bg-opacity-10 text-teal-50;
+ }
+
+ .badge-warning {
+ @apply bg-yellow-40 bg-opacity-20 text-yellow-60;
+ }
+
+ .badge-ghost {
+ @apply text-grey-90 border border-grey-20 whitespace-nowrap;
+ }
+
+ .badge-default {
+ @apply inter-small-regular bg-grey-10 text-grey-90 whitespace-nowrap;
+ }
+
+ .btn {
+ @apply flex items-center justify-center rounded-rounded focus:outline-none focus:shadow-cta;
+ }
+
+ .btn-large {
+ @apply inter-base-semibold px-large py-small;
+ }
+
+ .btn-medium {
+ @apply inter-base-semibold px-base py-xsmall;
+ }
+
+ .btn-small {
+ @apply inter-small-semibold px-small py-[6px];
+ }
+
+ .btn-primary {
+ @apply bg-violet-60 text-grey-0 hover:bg-violet-50 active:bg-violet-70 disabled:bg-grey-20 disabled:text-grey-40;
+ }
+
+ .btn-secondary {
+ @apply bg-grey-0 text-grey-90 border border-grey-20 hover:bg-grey-5 active:bg-grey-5 active:text-violet-60 focus:border-violet-60 disabled:bg-grey-0 disabled:text-grey-30;
+ }
+
+ .btn-danger {
+ @apply bg-grey-0 text-rose-50 border border-grey-20 hover:bg-grey-10 active:bg-grey-20 disabled:bg-grey-0 disabled:text-grey-30;
+ }
+
+ .btn-nuclear {
+ @apply bg-rose-50 text-grey-0 hover:bg-rose-40 active:bg-rose-60 disabled:bg-grey-20 disabled:text-grey-40;
+ }
+
+ .btn-ghost {
+ @apply bg-transparent text-grey-90 hover:bg-grey-5 active:bg-grey-5 active:text-violet-60 focus:border-violet-60 disabled:bg-transparent disabled:text-grey-30;
+ }
+
+ .btn-primary-large {
+ @apply btn btn-large btn-primary;
+ }
+ .btn-primary-medium {
+ @apply btn btn-medium;
+ }
+ .btn-primary-small {
+ @apply btn btn-small;
+ }
+ .btn-secondary-large {
+ @apply btn btn-large btn-seconday;
+ }
+ .btn-secondary-medium {
+ @apply btn btn-medium btn-seconday;
+ }
+ .btn-secondary-small {
+ @apply btn btn-small btn-seconday;
+ }
+ .btn-ghost-large {
+ @apply btn btn-large btn-ghost;
+ }
+ .btn-ghost-medium {
+ @apply btn btn-medium btn-ghost;
+ }
+ .btn-ghost-small {
+ @apply btn btn-small btn-ghost;
+ }
+}
+
+@layer components {
+ .date-picker {
+ @apply border-0 outline-none pt-6 !important;
+
+ .react-datepicker__month-container {
+ .react-datepicker__header {
+ @apply bg-inherit border-0;
+ }
+ }
+
+ .react-datepicker__day-names {
+ @apply inter-base-semibold pt-4;
+
+ .react-datepicker__day-name {
+ @apply w-[40px] m-0;
+ }
+ }
+
+ .react-datepicker__month {
+ @apply m-0;
+ }
+ .react-datepicker__day {
+ @apply inter-base-regular;
+ }
+ .react-datepicker__day--today {
+ @apply text-grey-90 inter-base-semibold bg-grey-10 rounded !important;
+ }
+
+ .react-datepicker__day--outside-month,
+ .past {
+ @apply text-grey-40 !important;
+ }
+
+ .date {
+ @apply text-grey-90 m-[0px] w-[38px] h-[38px] align-middle relative leading-none pt-3;
+ :hover {
+ @apply cursor-pointer;
+ }
+ }
+ .chosen,
+ .react-datepicker__day--keyboard-selected {
+ @apply bg-violet-60 text-grey-0 inter-base-semibold leading-none !important;
+ }
+ }
+
+ .time-list::-webkit-scrollbar {
+ /* chrome */
+ display: none;
+ }
+
+ .time-list {
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
+ }
+}
+
+@layer utilities {
+ /* Hide scrollbar for Chrome, Safari and Opera */
+ .no-scrollbar::-webkit-scrollbar {
+ display: none;
+ }
+
+ /* Hide scrollbar for IE, Edge and Firefox */
+ .no-scrollbar {
+ -ms-overflow-style: none; /* IE and Edge */
+ scrollbar-width: none; /* Firefox */
+ }
+
+ .vice-city {
+ @apply bg-gradient-to-tr from-vice-start to-vice-stop;
+ }
+
+ .hidden-actions[data-state="open"] {
+ opacity: 1;
+ }
+
+ input[type="number"]::-webkit-inner-spin-button,
+ input[type="number"]::-webkit-outer-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+ }
+
+ ::-webkit-scrollbar {
+ width: 4px;
+ height: 4px;
+ }
+
+ ::-webkit-scrollbar-track {
+ @apply bg-transparent;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ @apply rounded-rounded bg-grey-30;
+ }
+
+ ::-webkit-scrollbar-thumb:hover {
+ @apply bg-grey-40;
+ }
+
+ .accordion-margin-transition {
+ @apply transition-[margin] duration-300 ease-[cubic-bezier(0.87,0,0.13,1)];
+ }
+
+ .col-tree:last-child .bottom-half-dash {
+ @apply border-none;
+ }
+}
+
+.scrolling-touch {
+ -webkit-overflow-scrolling: touch;
+}
+.scrolling-auto {
+ -webkit-overflow-scrolling: auto;
+}
+
+/* Classes to remove number spinners from inputs of type number */
+/* Chrome, Safari, Edge, Opera */
+.remove-number-spinner::-webkit-outer-spin-button,
+.remove-number-spinner::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+/* Firefox */
+.remove-number-spinner {
+ -moz-appearance: textfield;
+}
diff --git a/packages/admin-ui/ui/src/assets/svg/carrot.svg b/packages/admin-ui/ui/src/assets/svg/carrot.svg
new file mode 100644
index 0000000000000..1209385b7dbc5
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/carrot.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/controller.svg b/packages/admin-ui/ui/src/assets/svg/controller.svg
new file mode 100644
index 0000000000000..ec4d9190be43c
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/controller.svg
@@ -0,0 +1,7 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/flag.svg b/packages/admin-ui/ui/src/assets/svg/flag.svg
new file mode 100644
index 0000000000000..9b204a3c5dd94
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/flag.svg
@@ -0,0 +1,4 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/happy.svg b/packages/admin-ui/ui/src/assets/svg/happy.svg
new file mode 100644
index 0000000000000..760ed1bbd4bf7
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/happy.svg
@@ -0,0 +1,6 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/heart.svg b/packages/admin-ui/ui/src/assets/svg/heart.svg
new file mode 100644
index 0000000000000..fd2ffbe89e1c9
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/heart.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/lightbulb.svg b/packages/admin-ui/ui/src/assets/svg/lightbulb.svg
new file mode 100644
index 0000000000000..2ee0d862823af
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/lightbulb.svg
@@ -0,0 +1,5 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/plane.svg b/packages/admin-ui/ui/src/assets/svg/plane.svg
new file mode 100644
index 0000000000000..3e321b9e09a43
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/plane.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/search.svg b/packages/admin-ui/ui/src/assets/svg/search.svg
new file mode 100644
index 0000000000000..69cc6547ce031
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/search.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/sprout.svg b/packages/admin-ui/ui/src/assets/svg/sprout.svg
new file mode 100644
index 0000000000000..0742a10337a67
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/sprout.svg
@@ -0,0 +1,6 @@
+
diff --git a/packages/admin-ui/ui/src/assets/svg/star.svg b/packages/admin-ui/ui/src/assets/svg/star.svg
new file mode 100644
index 0000000000000..2d3ff1bd3e1d8
--- /dev/null
+++ b/packages/admin-ui/ui/src/assets/svg/star.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/admin-ui/ui/src/components/atoms/avatar/index.tsx b/packages/admin-ui/ui/src/components/atoms/avatar/index.tsx
new file mode 100644
index 0000000000000..9912beabe9e5a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/avatar/index.tsx
@@ -0,0 +1,62 @@
+import * as RadixAvatar from "@radix-ui/react-avatar"
+import clsx from "clsx"
+import React from "react"
+import Spinner from "../spinner"
+
+type AvatarProps = {
+ user?: {
+ img?: string
+ first_name?: string
+ last_name?: string
+ email?: string
+ }
+ font?: string
+ color?: string
+ isLoading?: boolean
+}
+
+const Avatar: React.FC = ({
+ user,
+ font = "inter-small-semibold",
+ color = "bg-violet-60",
+ isLoading = false,
+}) => {
+ let username: string
+
+ if (user?.first_name && user?.last_name) {
+ username = user.first_name + " " + user.last_name
+ } else if (user?.email) {
+ username = user.email
+ } else {
+ username = "Medusa user"
+ }
+
+ return (
+
+
+
+ {isLoading ? (
+
+ ) : (
+ username.slice(0, 1).toUpperCase()
+ )}
+
+
+ )
+}
+
+export default Avatar
diff --git a/packages/admin-ui/ui/src/components/atoms/back-button/index.tsx b/packages/admin-ui/ui/src/components/atoms/back-button/index.tsx
new file mode 100644
index 0000000000000..bdeba612363f2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/back-button/index.tsx
@@ -0,0 +1,29 @@
+import clsx from "clsx"
+import React from "react"
+import { useNavigate } from "react-router-dom"
+import ArrowLeftIcon from "../../fundamentals/icons/arrow-left-icon"
+
+type Props = {
+ path?: string
+ label?: string
+ className?: string
+}
+
+const BackButton = ({ path, label = "Go back", className }: Props) => {
+ const navigate = useNavigate()
+ return (
+
+ )
+}
+
+export default BackButton
diff --git a/packages/admin-ui/ui/src/components/atoms/checkbox/index.tsx b/packages/admin-ui/ui/src/components/atoms/checkbox/index.tsx
new file mode 100644
index 0000000000000..2e4fa8dca7ed8
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/checkbox/index.tsx
@@ -0,0 +1,32 @@
+import clsx from "clsx"
+import React, { ReactNode, useImperativeHandle } from "react"
+
+export type CheckboxProps = React.InputHTMLAttributes & {
+ label: ReactNode
+}
+
+const Checkbox = React.forwardRef(
+ ({ label, value, className, id, ...rest }: CheckboxProps, ref) => {
+ const checkboxRef = React.useRef(null)
+
+ useImperativeHandle(ref, () => checkboxRef.current)
+ return (
+
+ )
+ }
+)
+
+export default Checkbox
diff --git a/packages/admin-ui/ui/src/components/atoms/copy-to-clipboard/index.tsx b/packages/admin-ui/ui/src/components/atoms/copy-to-clipboard/index.tsx
new file mode 100644
index 0000000000000..7b46e054d2d71
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/copy-to-clipboard/index.tsx
@@ -0,0 +1,58 @@
+import clsx from "clsx"
+import React, { useEffect } from "react"
+import useClipboard from "../../../hooks/use-clipboard"
+import useNotification from "../../../hooks/use-notification"
+import Button from "../../fundamentals/button"
+import ClipboardCopyIcon from "../../fundamentals/icons/clipboard-copy-icon"
+
+type CopyToClipboardProps = {
+ value: string
+ displayValue?: string
+ successDuration?: number
+ showValue?: boolean
+ iconSize?: number
+ onCopy?: () => void
+}
+
+const CopyToClipboard: React.FC = ({
+ value,
+ displayValue,
+ successDuration = 3000,
+ showValue = true,
+ iconSize = 20,
+ onCopy = () => {},
+}) => {
+ const [isCopied, handleCopy] = useClipboard(value, {
+ onCopied: onCopy,
+ successDuration: successDuration,
+ })
+ const notification = useNotification()
+
+ useEffect(() => {
+ if (isCopied) {
+ notification("Success", "Copied!", "success")
+ }
+ }, [isCopied])
+
+ return (
+
+
+ {showValue && (
+
+ {displayValue ? displayValue : value}
+
+ )}
+
+ )
+}
+
+export default CopyToClipboard
diff --git a/packages/admin-ui/ui/src/components/atoms/date-picker/custom-header.tsx b/packages/admin-ui/ui/src/components/atoms/date-picker/custom-header.tsx
new file mode 100644
index 0000000000000..bfb99e0f595af
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/date-picker/custom-header.tsx
@@ -0,0 +1,44 @@
+import { ReactDatePickerCustomHeaderProps } from "react-datepicker"
+import NativeSelect from "../../molecules/native-select"
+import { getYearRange, monthNames } from "./utils"
+
+const CustomHeader = ({
+ date,
+ changeYear,
+ changeMonth,
+}: ReactDatePickerCustomHeaderProps) => {
+ const month = date.getMonth()
+ const monthName = monthNames[month]
+
+ const year = date.getFullYear()
+ return (
+
+
+ changeMonth(monthNames.indexOf(v))}
+ >
+ {monthNames.map((month) => (
+
+ {month}
+
+ ))}
+
+
+
+ changeYear(parseInt(v, 10))}
+ >
+ {getYearRange().map((year) => (
+
+ {year.toString()}
+
+ ))}
+
+
+
+ )
+}
+
+export default CustomHeader
diff --git a/packages/admin-ui/ui/src/components/atoms/date-picker/date-picker.tsx b/packages/admin-ui/ui/src/components/atoms/date-picker/date-picker.tsx
new file mode 100644
index 0000000000000..165b263018429
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/date-picker/date-picker.tsx
@@ -0,0 +1,115 @@
+import * as PopoverPrimitive from "@radix-ui/react-popover"
+import clsx from "clsx"
+import moment from "moment"
+import React, { useEffect, useState } from "react"
+import ReactDatePicker from "react-datepicker"
+import "react-datepicker/dist/react-datepicker.css"
+import Button from "../../fundamentals/button"
+import ArrowDownIcon from "../../fundamentals/icons/arrow-down-icon"
+import InputContainer from "../../fundamentals/input-container"
+import InputHeader from "../../fundamentals/input-header"
+import CustomHeader from "./custom-header"
+import { DateTimePickerProps } from "./types"
+
+const getDateClassname = (d, tempDate) => {
+ return moment(d).format("YY,MM,DD") === moment(tempDate).format("YY,MM,DD")
+ ? "date chosen"
+ : `date ${
+ moment(d).format("YY,MM,DD") < moment(new Date()).format("YY,MM,DD")
+ ? "past"
+ : ""
+ }`
+}
+
+const DatePicker: React.FC = ({
+ date,
+ onSubmitDate,
+ label = "start date",
+ required = false,
+ tooltipContent,
+ tooltip,
+}) => {
+ const [tempDate, setTempDate] = useState(date)
+ const [isOpen, setIsOpen] = useState(false)
+
+ useEffect(() => setTempDate(date), [isOpen])
+
+ const submitDate = () => {
+ // update only date, month and year
+ const newDate = new Date(date.getTime())
+ newDate.setUTCDate(tempDate.getUTCDate())
+ newDate.setUTCMonth(tempDate.getUTCMonth())
+ newDate.setUTCFullYear(tempDate.getUTCFullYear())
+
+ onSubmitDate(newDate)
+ setIsOpen(false)
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export const CalendarComponent = ({ date, onChange }) => (
+ getDateClassname(d, date)}
+ renderCustomHeader={({ ...props }) => }
+ />
+)
+
+export default DatePicker
diff --git a/packages/admin-ui/ui/src/components/atoms/date-picker/time-picker.tsx b/packages/admin-ui/ui/src/components/atoms/date-picker/time-picker.tsx
new file mode 100644
index 0000000000000..f0f62f943b333
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/date-picker/time-picker.tsx
@@ -0,0 +1,102 @@
+import * as PopoverPrimitive from "@radix-ui/react-popover"
+import clsx from "clsx"
+import { isNil } from "lodash"
+import moment from "moment"
+import React, { useEffect, useState } from "react"
+import ArrowDownIcon from "../../fundamentals/icons/arrow-down-icon"
+import ClockIcon from "../../fundamentals/icons/clock-icon"
+import InputContainer from "../../fundamentals/input-container"
+import InputHeader from "../../fundamentals/input-header"
+import NumberScroller from "../number-scroller"
+import { DateTimePickerProps } from "./types"
+
+const TimePicker: React.FC = ({
+ date,
+ onSubmitDate,
+ label = "start date",
+ required = false,
+ tooltipContent,
+ tooltip,
+}) => {
+ const [selectedMinute, setSelectedMinute] = useState(
+ new Date(date)?.getUTCMinutes()
+ )
+ const [selectedHour, setSelectedHour] = useState(
+ new Date(date)?.getUTCHours()
+ )
+
+ useEffect(() => {
+ setSelectedMinute(new Date(date)?.getUTCMinutes())
+ setSelectedHour(new Date(date)?.getUTCHours())
+ }, [date])
+
+ useEffect(() => {
+ if (date && !isNil(selectedHour) && !isNil(selectedMinute)) {
+ const newDate = new Date(new Date(date).getTime())
+ newDate.setUTCHours(selectedHour)
+ newDate.setUTCMinutes(selectedMinute)
+ onSubmitDate(newDate)
+ }
+ }, [selectedMinute, selectedHour])
+
+ const [isOpen, setIsOpen] = useState(false)
+
+ const minuteNumbers = [...Array(60).keys()]
+ const hourNumbers = [...Array(24).keys()]
+
+ return (
+
+
+
+
+
+
+ setSelectedHour(n)}
+ className="pr-4"
+ />
+ setSelectedMinute(n)}
+ />
+
+
+
+
+ )
+}
+
+export default TimePicker
diff --git a/packages/admin-ui/ui/src/components/atoms/date-picker/types.tsx b/packages/admin-ui/ui/src/components/atoms/date-picker/types.tsx
new file mode 100644
index 0000000000000..88b4d662d039f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/date-picker/types.tsx
@@ -0,0 +1,6 @@
+import { InputHeaderProps } from "../../fundamentals/input-header"
+
+export type DateTimePickerProps = {
+ date: Date
+ onSubmitDate: (newDate: Date) => void
+} & InputHeaderProps
diff --git a/packages/admin-ui/ui/src/components/atoms/date-picker/utils.ts b/packages/admin-ui/ui/src/components/atoms/date-picker/utils.ts
new file mode 100644
index 0000000000000..d46746616b741
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/date-picker/utils.ts
@@ -0,0 +1,25 @@
+export const range = (start, end) => {
+ const range: number[] = []
+ for (let i = start; i <= end; i++) {
+ range.push(i)
+ }
+ return range
+}
+
+export const getYearRange = (step = 20) =>
+ range(new Date().getFullYear() - step, new Date().getFullYear() + step)
+
+export const monthNames = [
+ "January",
+ "February",
+ "March",
+ "April",
+ "May",
+ "June",
+ "July",
+ "August",
+ "September",
+ "October",
+ "November",
+ "December",
+]
diff --git a/packages/admin-ui/ui/src/components/atoms/fade-wrapper/index.tsx b/packages/admin-ui/ui/src/components/atoms/fade-wrapper/index.tsx
new file mode 100644
index 0000000000000..2594591b8e668
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/fade-wrapper/index.tsx
@@ -0,0 +1,47 @@
+import clsx from "clsx"
+import React, { useEffect, useState } from "react"
+
+type FadeProps = {
+ isVisible: boolean
+ isFullScreen?: boolean
+ start?: string
+ transitionClass?: string
+ end?: string
+ classname?: string
+ children?: React.ReactNode
+}
+
+const Fade: React.FC = ({
+ isVisible,
+ start,
+ end,
+ classname,
+ children,
+ isFullScreen = false,
+}) => {
+ const [show, setShow] = useState(false)
+
+ useEffect(() => {
+ if (show && !isVisible) {
+ setTimeout(() => setShow(false), 100)
+ } else {
+ setShow(isVisible)
+ }
+ })
+
+ const classes = {
+ [start || "scale-[0.98] opacity-0"]: !isVisible,
+ [end || "scale-100 opacity-100"]: isVisible,
+ "absolute inset-0": show && isFullScreen,
+ }
+
+ return (
+
+ {show ? children : null}
+
+ )
+}
+
+export default Fade
diff --git a/packages/admin-ui/ui/src/components/atoms/file-upload-field/index.tsx b/packages/admin-ui/ui/src/components/atoms/file-upload-field/index.tsx
new file mode 100644
index 0000000000000..265700c5cd63f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/file-upload-field/index.tsx
@@ -0,0 +1,105 @@
+import clsx from "clsx"
+import React, { useRef, useState } from "react"
+
+type FileUploadFieldProps = {
+ onFileChosen: (files: File[]) => void
+ filetypes: string[]
+ errorMessage?: string
+ placeholder?: React.ReactElement | string
+ className?: string
+ multiple?: boolean
+ text?: React.ReactElement | string
+}
+
+const defaultText = (
+
+ Drop your images here, or{" "}
+ click to browse
+
+)
+
+const FileUploadField: React.FC = ({
+ onFileChosen,
+ filetypes,
+ errorMessage,
+ className,
+ text = defaultText,
+ placeholder = "",
+ multiple = false,
+}) => {
+ const inputRef = useRef(null)
+ const [fileUploadError, setFileUploadError] = useState(false)
+
+ const handleFileUpload = (e: React.ChangeEvent) => {
+ const fileList = e.target.files
+
+ if (fileList) {
+ onFileChosen(Array.from(fileList))
+ }
+ }
+
+ const handleFileDrop = (e: React.DragEvent) => {
+ setFileUploadError(false)
+
+ e.preventDefault()
+
+ const files: File[] = []
+
+ if (e.dataTransfer.items) {
+ // Use DataTransferItemList interface to access the file(s)
+ for (let i = 0; i < e.dataTransfer.items.length; i++) {
+ // If dropped items aren't files, reject them
+ if (e.dataTransfer.items[i].kind === "file") {
+ const file = e.dataTransfer.items[i].getAsFile()
+ if (file && filetypes.indexOf(file.type) > -1) {
+ files.push(file)
+ }
+ }
+ }
+ } else {
+ // Use DataTransfer interface to access the file(s)
+ for (let i = 0; i < e.dataTransfer.files.length; i++) {
+ if (filetypes.indexOf(e.dataTransfer.files[i].type) > -1) {
+ files.push(e.dataTransfer.files[i])
+ }
+ }
+ }
+ if (files.length === 1) {
+ onFileChosen(files)
+ } else {
+ setFileUploadError(true)
+ }
+ }
+
+ return (
+ inputRef?.current?.click()}
+ onDrop={handleFileDrop}
+ onDragOver={(e) => e.preventDefault()}
+ className={clsx(
+ "flex flex-col select-none inter-base-regular text-grey-50 cursor-pointer items-center justify-center w-full h-full rounded-rounded border-2 border-dashed border-grey-20 transition-colors hover:border-violet-60 hover:text-grey-40",
+ className
+ )}
+ >
+
+
{text}
+ {placeholder}
+
+ {fileUploadError && (
+
+ {errorMessage || "Please upload an image file"}
+
+ )}
+
+
+ )
+}
+
+export default FileUploadField
diff --git a/packages/admin-ui/ui/src/components/atoms/includes-tax-tooltip/index.tsx b/packages/admin-ui/ui/src/components/atoms/includes-tax-tooltip/index.tsx
new file mode 100644
index 0000000000000..9f25abb610637
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/includes-tax-tooltip/index.tsx
@@ -0,0 +1,26 @@
+import clsx from "clsx"
+import React from "react"
+import TaxesIcon from "../../fundamentals/icons/taxes-icon"
+import Tooltip from "../tooltip"
+
+type Props = {
+ includesTax?: boolean
+}
+
+const IncludesTaxTooltip = ({ includesTax }: Props) => {
+ return (
+
+
+
+
+
+ )
+}
+
+export default IncludesTaxTooltip
diff --git a/packages/admin-ui/ui/src/components/atoms/input-error/index.tsx b/packages/admin-ui/ui/src/components/atoms/input-error/index.tsx
new file mode 100644
index 0000000000000..23ad952658e9d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/input-error/index.tsx
@@ -0,0 +1,73 @@
+import { ErrorMessage } from "@hookform/error-message"
+import clsx from "clsx"
+import React from "react"
+import { MultipleFieldErrors } from "react-hook-form"
+import Tooltip from "../tooltip"
+
+type InputErrorProps = {
+ errors?: { [x: string]: unknown }
+ name?: string
+ className?: string
+}
+
+const InputError = ({ errors, name, className }: InputErrorProps) => {
+ if (!errors || !name) {
+ return null
+ }
+
+ return (
+ {
+ return (
+
+ {messages ? (
+
+ ) : (
+
{message}
+ )}
+
+ )
+ }}
+ />
+ )
+}
+
+const MultipleMessages = ({ messages }: { messages: MultipleFieldErrors }) => {
+ const errors = Object.entries(messages).map(([_, message]) => message)
+
+ const displayedError = errors[0]
+ const remainderErrors = errors.slice(1)
+
+ return (
+
+
{displayedError}
+ {remainderErrors?.length > 0 && (
+
+ {remainderErrors.map((e, i) => {
+ return (
+
+ {Array.from(Array(i + 1)).map((_) => "*")}
+ {e}
+
+ )
+ })}
+
+ }
+ >
+
+ +{remainderErrors.length}{" "}
+ {remainderErrors.length > 1 ? "errors" : "error"}
+
+
+ )}
+
+ )
+}
+
+export default InputError
diff --git a/packages/admin-ui/ui/src/components/atoms/loading-container/index.tsx b/packages/admin-ui/ui/src/components/atoms/loading-container/index.tsx
new file mode 100644
index 0000000000000..6b5778f6eeade
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/loading-container/index.tsx
@@ -0,0 +1,32 @@
+import * as React from "react"
+import Spinner from "../spinner"
+
+type LoadingContainerProps = {
+ isLoading: boolean
+ placeholder?: React.ReactElement
+ children: React.ReactElement | React.ReactElement[]
+}
+
+const LoadingContainer = ({
+ isLoading,
+ children,
+ placeholder,
+ ...props
+}: LoadingContainerProps) => {
+ placeholder = placeholder ||
+
+ if (isLoading) {
+ return (
+
+ {placeholder}
+
+ )
+ }
+
+ return children as React.ReactElement
+}
+
+export default LoadingContainer
diff --git a/packages/admin-ui/ui/src/components/atoms/notification/index.tsx b/packages/admin-ui/ui/src/components/atoms/notification/index.tsx
new file mode 100644
index 0000000000000..3a5f6f7f376f0
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/notification/index.tsx
@@ -0,0 +1,62 @@
+import React from "react"
+import type { Toast } from "react-hot-toast"
+import { toast as globalToast } from "react-hot-toast"
+import AlertIcon from "../../fundamentals/icons/alert-icon"
+import CheckCircleIcon from "../../fundamentals/icons/check-circle-icon"
+import CrossIcon from "../../fundamentals/icons/cross-icon"
+import InfoIcon from "../../fundamentals/icons/info-icon"
+import XCircleIcon from "../../fundamentals/icons/x-circle-icon"
+import ToasterContainer from "../toaster-container"
+
+export type NotificationTypes = "success" | "warning" | "error" | "info"
+
+type NotificationProps = {
+ toast: Toast
+ type: NotificationTypes
+ title: string
+ message: string
+}
+
+const Notification: React.FC = ({
+ toast,
+ type,
+ title,
+ message,
+}) => {
+ const onDismiss = () => {
+ globalToast.dismiss(toast.id)
+ }
+
+ return (
+
+ {getIcon(type)}
+
+ {title}
+ {message}
+
+
+
+ Close
+
+
+ )
+}
+
+const ICON_SIZE = 20
+
+function getIcon(type: NotificationTypes) {
+ switch (type) {
+ case "success":
+ return
+ case "warning":
+ return
+ case "error":
+ return
+ default:
+ return
+ }
+}
+
+export default Notification
diff --git a/packages/admin-ui/ui/src/components/atoms/number-scroller/index.tsx b/packages/admin-ui/ui/src/components/atoms/number-scroller/index.tsx
new file mode 100644
index 0000000000000..514b901d7cbb5
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/number-scroller/index.tsx
@@ -0,0 +1,47 @@
+import clsx from "clsx"
+import React from "react"
+
+type NumberScrollerProps = {
+ numbers: number[]
+ selected: number
+ onSelect: (value: number) => void
+} & React.HTMLAttributes
+
+const NumberScroller: React.FC = ({
+ numbers,
+ selected,
+ onSelect,
+ className,
+ ...props
+}) => {
+ return (
+
+ {numbers.map((n, i) => {
+ return (
+
+
+
+ )
+ })}
+
+ )
+}
+
+export default NumberScroller
diff --git a/packages/admin-ui/ui/src/components/atoms/os-shortcut/index.tsx b/packages/admin-ui/ui/src/components/atoms/os-shortcut/index.tsx
new file mode 100644
index 0000000000000..74f419573236b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/os-shortcut/index.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+
+type OSShortcutProps = {
+ winModifiers: string | string[]
+ macModifiers: string | string[]
+ keys: string[] | string
+}
+
+const OSShortcut = ({ winModifiers, macModifiers, keys }: OSShortcutProps) => {
+ const isMac =
+ typeof window !== "undefined" &&
+ navigator?.platform?.toUpperCase().indexOf("MAC") >= 0
+ ? true
+ : false
+
+ let modifiers: string
+
+ if (isMac) {
+ if (Array.isArray(macModifiers)) {
+ modifiers = macModifiers.join("")
+ } else {
+ modifiers = macModifiers
+ }
+ } else {
+ if (Array.isArray(winModifiers)) {
+ modifiers = winModifiers.join(" + ")
+ } else {
+ modifiers = winModifiers
+ }
+ }
+
+ let input: string
+
+ if (Array.isArray(keys)) {
+ input = keys.join(" + ")
+ } else {
+ input = keys
+ }
+
+ return (
+
+
+ {modifiers}
+ {input}
+
+
+ )
+}
+
+export default OSShortcut
diff --git a/packages/admin-ui/ui/src/components/atoms/page-description/index.tsx b/packages/admin-ui/ui/src/components/atoms/page-description/index.tsx
new file mode 100644
index 0000000000000..899bc836dea2a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/page-description/index.tsx
@@ -0,0 +1,20 @@
+import React from "react"
+
+type PageDescriptionProps = {
+ title?: string
+ subtitle?: string
+}
+
+const PageDescription: React.FC = ({
+ title,
+ subtitle,
+}) => {
+ return (
+
+
{title}
+ {subtitle}
+
+ )
+}
+
+export default PageDescription
diff --git a/packages/admin-ui/ui/src/components/atoms/save-notification/error-state.tsx b/packages/admin-ui/ui/src/components/atoms/save-notification/error-state.tsx
new file mode 100644
index 0000000000000..e84d1d47bc129
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/save-notification/error-state.tsx
@@ -0,0 +1,49 @@
+import React, { useEffect } from "react"
+import type { Toast } from "react-hot-toast"
+import CrossIcon from "../../fundamentals/icons/cross-icon"
+import XCircleIcon from "../../fundamentals/icons/x-circle-icon"
+import ToasterContainer from "../toaster-container"
+
+type SavingStateProps = {
+ toast: Toast
+ title?: string
+ message?: string
+ onDismiss: () => void
+}
+
+const ErrorState: React.FC = ({
+ toast,
+ title = "Error",
+ message = "An error occured while trying to save your changes. Please try again.",
+ onDismiss,
+}) => {
+ useEffect(() => {
+ const life = setTimeout(() => {
+ onDismiss()
+ }, 2000)
+
+ return () => {
+ clearTimeout(life)
+ }
+ }, [toast])
+
+ return (
+
+
+
+
+
+ {title}
+ {message}
+
+
+
+ Close
+
+
+ )
+}
+
+export default ErrorState
diff --git a/packages/admin-ui/ui/src/components/atoms/save-notification/index.tsx b/packages/admin-ui/ui/src/components/atoms/save-notification/index.tsx
new file mode 100644
index 0000000000000..d86745f93fff2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/save-notification/index.tsx
@@ -0,0 +1,94 @@
+import React, { ReactNode } from "react"
+import type { Toast } from "react-hot-toast"
+import { toast as globalToast } from "react-hot-toast"
+import RefreshIcon from "../../fundamentals/icons/refresh-icon"
+import ToasterContainer from "../toaster-container"
+import ErrorState from "./error-state"
+import SavingState from "./saving-state"
+import SuccessState from "./success-state"
+
+type SaveNotificationProps = {
+ toast: Toast
+ icon?: ReactNode
+ title?: string
+ message?: string
+ onSave: () => Promise
+ reset: () => void
+}
+
+const SaveNotification: React.FC = ({
+ toast,
+ icon,
+ title = "Unsaved changes",
+ message = "You have unsaved changes. Do you want to save and publish or discard them?",
+ onSave,
+ reset,
+}) => {
+ const onDismiss = () => {
+ reset()
+ globalToast.dismiss(toast.id)
+ }
+
+ const handleSave = () => {
+ globalToast.custom((t) => , {
+ id: toast.id,
+ })
+
+ onSave()
+ .then(() => {
+ globalToast.custom(
+ (t) => ,
+ {
+ id: toast.id,
+ }
+ )
+ })
+ .catch((_err) => {
+ globalToast.custom(
+ (t) => ,
+ {
+ id: toast.id,
+ }
+ )
+ })
+ }
+
+ return (
+
+ {getIcon(icon)}
+
+ {title}
+ {message}
+
+
+
+
+
+
+ )
+}
+
+const ICON_SIZE = 20
+
+function getIcon(icon?: any) {
+ if (icon) {
+ return React.cloneElement(icon, {
+ size: ICON_SIZE,
+ className: "text-grey-90",
+ })
+ } else {
+ return
+ }
+}
+
+export default SaveNotification
diff --git a/packages/admin-ui/ui/src/components/atoms/save-notification/saving-state.tsx b/packages/admin-ui/ui/src/components/atoms/save-notification/saving-state.tsx
new file mode 100644
index 0000000000000..feb481e02db80
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/save-notification/saving-state.tsx
@@ -0,0 +1,30 @@
+import React from "react"
+import type { Toast } from "react-hot-toast"
+import Spinner from "../spinner"
+import ToasterContainer from "../toaster-container"
+
+type SavingStateProps = {
+ toast: Toast
+ title?: string
+ message?: string
+}
+
+const SavingState: React.FC = ({
+ toast,
+ title = "Saving changes",
+ message = "Hang on, this may take a few moments.",
+}) => {
+ return (
+
+
+
+
+
+ {title}
+ {message}
+
+
+ )
+}
+
+export default SavingState
diff --git a/packages/admin-ui/ui/src/components/atoms/save-notification/success-state.tsx b/packages/admin-ui/ui/src/components/atoms/save-notification/success-state.tsx
new file mode 100644
index 0000000000000..007eadbff99f7
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/save-notification/success-state.tsx
@@ -0,0 +1,49 @@
+import React, { useEffect } from "react"
+import type { Toast } from "react-hot-toast"
+import CheckCircleIcon from "../../fundamentals/icons/check-circle-icon"
+import CrossIcon from "../../fundamentals/icons/cross-icon"
+import ToasterContainer from "../toaster-container"
+
+type SavingStateProps = {
+ toast: Toast
+ title?: string
+ message?: string
+ onDismiss: () => void
+}
+
+const SuccessState: React.FC = ({
+ toast,
+ title = "Success",
+ message = "Your changes have been saved.",
+ onDismiss,
+}) => {
+ useEffect(() => {
+ const life = setTimeout(() => {
+ onDismiss()
+ }, 2000)
+
+ return () => {
+ clearTimeout(life)
+ }
+ }, [toast])
+
+ return (
+
+
+
+
+
+ {title}
+ {message}
+
+
+
+ Close
+
+
+ )
+}
+
+export default SuccessState
diff --git a/packages/admin-ui/ui/src/components/atoms/settings-card/index.tsx b/packages/admin-ui/ui/src/components/atoms/settings-card/index.tsx
new file mode 100644
index 0000000000000..f9085766b26f7
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/settings-card/index.tsx
@@ -0,0 +1,56 @@
+import React from "react"
+import { Link } from "react-router-dom"
+import ChevronRightIcon from "../../fundamentals/icons/chevron-right-icon"
+
+type SettingsCardProps = {
+ icon: React.ReactNode
+ heading: string
+ description: string
+ to?: string
+ externalLink?: string
+ disabled?: boolean
+}
+
+const SettingsCard: React.FC = ({
+ icon,
+ heading,
+ description,
+ to = null,
+ externalLink = null,
+ disabled = false,
+}) => {
+ if (disabled) {
+ to = null
+ }
+
+ return (
+
+
+
+ )
+}
+
+export default SettingsCard
diff --git a/packages/admin-ui/ui/src/components/atoms/skeleton/index.tsx b/packages/admin-ui/ui/src/components/atoms/skeleton/index.tsx
new file mode 100644
index 0000000000000..993939e378eb7
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/skeleton/index.tsx
@@ -0,0 +1,25 @@
+import clsx from "clsx"
+import { PropsWithChildren } from "react"
+import { useSkeleton } from "../../../providers/skeleton-provider"
+
+type Props = PropsWithChildren<{
+ isLoading?: boolean
+}>
+
+const Skeleton = ({ children, isLoading }: Props) => {
+ const { isLoading: providerState = false } = useSkeleton()
+
+ const state = isLoading || providerState
+
+ return (
+ *]:opacity-0": state,
+ })}
+ >
+ {children}
+
+ )
+}
+
+export default Skeleton
diff --git a/packages/admin-ui/ui/src/components/atoms/spinner.tsx b/packages/admin-ui/ui/src/components/atoms/spinner.tsx
new file mode 100644
index 0000000000000..f00aaeb8b3a57
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/spinner.tsx
@@ -0,0 +1,35 @@
+import clsx from "clsx"
+import React from "react"
+
+type SpinnerProps = {
+ size?: "large" | "medium" | "small"
+ variant?: "primary" | "secondary"
+}
+
+const Spinner: React.FC = ({
+ size = "large",
+ variant = "primary",
+}) => {
+ return (
+
+ )
+}
+
+export default Spinner
diff --git a/packages/admin-ui/ui/src/components/atoms/switch/index.tsx b/packages/admin-ui/ui/src/components/atoms/switch/index.tsx
new file mode 100644
index 0000000000000..6db8450990784
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/switch/index.tsx
@@ -0,0 +1,26 @@
+import * as RadixSwitch from "@radix-ui/react-switch"
+import clsx from "clsx"
+import React from "react"
+
+/**
+ * A controlled switch component atom.
+ */
+function Switch(props: RadixSwitch.SwitchProps) {
+ return (
+
+
+
+ )
+}
+
+export default Switch
diff --git a/packages/admin-ui/ui/src/components/atoms/text-input/index.tsx b/packages/admin-ui/ui/src/components/atoms/text-input/index.tsx
new file mode 100644
index 0000000000000..15a6a585f4c20
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/text-input/index.tsx
@@ -0,0 +1,19 @@
+import React from "react"
+import clsx from "clsx"
+
+type TextInputProps = React.InputHTMLAttributes
+
+const TextInput = React.forwardRef(
+ ({ className, ...props }, ref) => (
+
+ )
+)
+
+export default TextInput
diff --git a/packages/admin-ui/ui/src/components/atoms/thumbnail/index.ts b/packages/admin-ui/ui/src/components/atoms/thumbnail/index.ts
new file mode 100644
index 0000000000000..e42d9e98f6c59
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/thumbnail/index.ts
@@ -0,0 +1 @@
+export { Thumbnail as default } from "./thumbnail"
diff --git a/packages/admin-ui/ui/src/components/atoms/thumbnail/thumbnail.tsx b/packages/admin-ui/ui/src/components/atoms/thumbnail/thumbnail.tsx
new file mode 100644
index 0000000000000..2f463c8ad7a6b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/thumbnail/thumbnail.tsx
@@ -0,0 +1,30 @@
+import clsx from "clsx"
+import ImagePlaceholderIcon from "../../fundamentals/icons/image-placeholder-icon"
+
+type Props = {
+ src?: string | null
+ className?: string
+ size?: "small" | "medium" | "large"
+}
+
+export const Thumbnail = ({ src, className, size = "small" }: Props) => {
+ return (
+
+ {src ? (
+

+ ) : (
+
+ )}
+
+ )
+}
diff --git a/packages/admin-ui/ui/src/components/atoms/toaster-container/index.tsx b/packages/admin-ui/ui/src/components/atoms/toaster-container/index.tsx
new file mode 100644
index 0000000000000..e165b9c8e7b7d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/toaster-container/index.tsx
@@ -0,0 +1,33 @@
+import clsx from "clsx"
+import React from "react"
+
+type ToasterContainerProps = {
+ visible: boolean
+} & React.HTMLAttributes
+
+const ToasterContainer: React.FC = ({
+ children,
+ visible,
+ className,
+ ...rest
+}) => {
+ return (
+
+ {children}
+
+ )
+}
+
+export default ToasterContainer
diff --git a/packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx b/packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx
new file mode 100644
index 0000000000000..9cf4d667ae66a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/tooltip/index.tsx
@@ -0,0 +1,58 @@
+import * as RadixTooltip from "@radix-ui/react-tooltip"
+import clsx from "clsx"
+import React from "react"
+
+export type TooltipProps = RadixTooltip.TooltipContentProps &
+ Pick<
+ RadixTooltip.TooltipProps,
+ "open" | "defaultOpen" | "onOpenChange" | "delayDuration"
+ > & {
+ content: React.ReactNode
+ side?: "bottom" | "left" | "top" | "right"
+ onClick?: React.ButtonHTMLAttributes["onClick"]
+ }
+
+const Tooltip = ({
+ children,
+ content,
+ open,
+ defaultOpen,
+ onOpenChange,
+ delayDuration,
+ className,
+ side,
+ onClick,
+ ...props
+}: TooltipProps) => {
+ return (
+
+
+
+ {children}
+
+
+ {content}
+
+
+
+ )
+}
+
+export default Tooltip
diff --git a/packages/admin-ui/ui/src/components/atoms/two-step-delete/index.tsx b/packages/admin-ui/ui/src/components/atoms/two-step-delete/index.tsx
new file mode 100644
index 0000000000000..5c7f85a6e19b8
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/atoms/two-step-delete/index.tsx
@@ -0,0 +1,110 @@
+import clsx from "clsx"
+import React, {
+ forwardRef,
+ useCallback,
+ useEffect,
+ useImperativeHandle,
+ useRef,
+ useState,
+} from "react"
+import TrashIcon from "../../fundamentals/icons/trash-icon"
+import Spinner from "../spinner"
+import Tooltip from "../tooltip"
+
+type Props = {
+ onDelete: () => void
+ deleting?: boolean
+ className?: string
+ children?: React.ReactNode
+}
+
+const TwoStepDelete = forwardRef(
+ ({ onDelete, deleting = false, children, className }: Props, ref) => {
+ const [armed, setArmed] = useState(false)
+ const innerRef = useRef(null)
+
+ useImperativeHandle(
+ ref,
+ () => innerRef.current
+ )
+
+ const handleTwoStepDelete = () => {
+ if (!armed) {
+ setArmed(true)
+ return
+ }
+
+ onDelete()
+ setArmed(false)
+ }
+
+ const disarmOnClickOutside = useCallback(
+ (e: MouseEvent) => {
+ if (innerRef.current && !innerRef.current.contains(e.target as Node)) {
+ if (armed) {
+ setArmed(false)
+ }
+ }
+ },
+ [armed]
+ )
+
+ useEffect(() => {
+ document.addEventListener("mousedown", disarmOnClickOutside)
+
+ return () => {
+ document.removeEventListener("mousedown", disarmOnClickOutside)
+ }
+ }, [disarmOnClickOutside])
+
+ return (
+
+ )
+ }
+)
+
+export default TwoStepDelete
diff --git a/packages/admin-ui/ui/src/components/declarative-toaster/index.tsx b/packages/admin-ui/ui/src/components/declarative-toaster/index.tsx
new file mode 100644
index 0000000000000..34ddfaf17e2e1
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/declarative-toaster/index.tsx
@@ -0,0 +1,23 @@
+import * as React from "react"
+import { toast, ToastOptions } from "react-hot-toast"
+
+export type ToasterProps = {
+ visible: boolean
+ children: React.ReactElement
+} & ToastOptions
+
+const Toaster = ({ visible, children, ...options }: ToasterProps) => {
+ React.useEffect(() => {
+ if (visible) {
+ toast.custom((t) => React.cloneElement(children, { toast: t }), {
+ ...options,
+ })
+ } else {
+ toast.dismiss(options.id)
+ }
+ }, [visible, children])
+
+ return null
+}
+
+export default Toaster
diff --git a/packages/admin-ui/ui/src/components/fundamentals/badge/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/badge/index.tsx
new file mode 100644
index 0000000000000..fd445a1d75270
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/badge/index.tsx
@@ -0,0 +1,43 @@
+import clsx from "clsx"
+import React from "react"
+
+type BadgeProps = {
+ variant:
+ | "primary"
+ | "danger"
+ | "success"
+ | "warning"
+ | "ghost"
+ | "default"
+ | "disabled"
+} & React.HTMLAttributes
+
+const Badge: React.FC = ({
+ children,
+ variant,
+ onClick,
+ className,
+ ...props
+}) => {
+ const variantClassname = clsx({
+ ["badge-primary"]: variant === "primary",
+ ["badge-danger"]: variant === "danger",
+ ["badge-success"]: variant === "success",
+ ["badge-warning"]: variant === "warning",
+ ["badge-ghost"]: variant === "ghost",
+ ["badge-default"]: variant === "default",
+ ["badge-disabled"]: variant === "disabled",
+ })
+
+ return (
+
+ {children}
+
+ )
+}
+
+export default Badge
diff --git a/packages/admin-ui/ui/src/components/fundamentals/button/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/button/index.tsx
new file mode 100644
index 0000000000000..c04a651724dbc
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/button/index.tsx
@@ -0,0 +1,71 @@
+import clsx from "clsx"
+import React, { Children } from "react"
+import Spinner from "../../atoms/spinner"
+
+export type ButtonProps = {
+ variant: "primary" | "secondary" | "ghost" | "danger" | "nuclear"
+ size?: "small" | "medium" | "large"
+ loading?: boolean
+} & React.ButtonHTMLAttributes
+
+const Button = React.forwardRef(
+ (
+ {
+ variant = "primary",
+ size = "large",
+ loading = false,
+ children,
+ ...attributes
+ },
+ ref
+ ) => {
+ const handleClick = (e) => {
+ if (!loading && attributes.onClick) {
+ attributes.onClick(e)
+ }
+ }
+
+ const variantClassname = clsx({
+ ["btn-primary"]: variant === "primary",
+ ["btn-secondary"]: variant === "secondary",
+ ["btn-ghost"]: variant === "ghost",
+ ["btn-danger"]: variant === "danger",
+ ["btn-nuclear"]: variant === "nuclear",
+ })
+
+ const sizeClassname = clsx({
+ ["btn-large"]: size === "large",
+ ["btn-medium"]: size === "medium",
+ ["btn-small"]: size === "small",
+ })
+
+ return (
+
+ )
+ }
+)
+
+export default Button
diff --git a/packages/admin-ui/ui/src/components/fundamentals/details-icon/contact.svg b/packages/admin-ui/ui/src/components/fundamentals/details-icon/contact.svg
new file mode 100644
index 0000000000000..d4fff1c3123b9
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/details-icon/contact.svg
@@ -0,0 +1,7 @@
+
diff --git a/packages/admin-ui/ui/src/components/fundamentals/details-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/details-icon/index.tsx
new file mode 100644
index 0000000000000..1e71482b85e3f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/details-icon/index.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "../icons/types/icon-type"
+
+const DetailsIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default DetailsIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/feature-toggle.tsx b/packages/admin-ui/ui/src/components/fundamentals/feature-toggle.tsx
new file mode 100644
index 0000000000000..6f97f6a2fded6
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/feature-toggle.tsx
@@ -0,0 +1,21 @@
+import React from "react"
+import { useFeatureFlag } from "../../providers/feature-flag-provider"
+
+export type FeatureToggleProps = {
+ featureFlag: string
+ showOnlyWhenDisabled?: boolean
+ children?: React.ReactNode
+}
+
+const FeatureToggle: React.FC = ({
+ featureFlag,
+ showOnlyWhenDisabled = false,
+ children,
+}) => {
+ const { isFeatureEnabled } = useFeatureFlag()
+
+ const showContent = isFeatureEnabled(featureFlag) === !showOnlyWhenDisabled
+ return showContent ? <>{children}> : null
+}
+
+export default FeatureToggle
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icon-badge/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icon-badge/index.tsx
new file mode 100644
index 0000000000000..5f30a61d09229
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icon-badge/index.tsx
@@ -0,0 +1,36 @@
+import clsx from "clsx"
+import React from "react"
+import Badge from "../badge"
+
+type IconBadgeProps = {
+ variant?:
+ | "primary"
+ | "danger"
+ | "success"
+ | "warning"
+ | "ghost"
+ | "default"
+ | "disabled"
+} & React.HTMLAttributes
+
+const IconBadge: React.FC = ({
+ children,
+ variant,
+ className,
+ ...rest
+}) => {
+ return (
+
+ {children}
+
+ )
+}
+
+export default IconBadge
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/alert-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/alert-icon/index.tsx
new file mode 100644
index 0000000000000..1fa57b92364bb
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/alert-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const AlertIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default AlertIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-down-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-down-icon.tsx
new file mode 100644
index 0000000000000..4590e3eea5119
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-down-icon.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const ArrowDownIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ArrowDownIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-left-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-left-icon/index.tsx
new file mode 100644
index 0000000000000..18bb2a165a95e
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-left-icon/index.tsx
@@ -0,0 +1,35 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ArrowLeftIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ArrowLeftIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-right-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-right-icon/index.tsx
new file mode 100644
index 0000000000000..a13f0961158c3
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-right-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ArrowRightIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ArrowRightIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-top-right-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-top-right-icon/index.tsx
new file mode 100644
index 0000000000000..3ced3262e8ba8
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-top-right-icon/index.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ArrowTopRightIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ArrowTopRightIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-up-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-up-icon.tsx
new file mode 100644
index 0000000000000..bee38736925a2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/arrow-up-icon.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const ArrowUpIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ArrowUpIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/back-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/back-icon/index.tsx
new file mode 100644
index 0000000000000..9892c086c22ba
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/back-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const BackIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default BackIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/backspace-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/backspace-icon/index.tsx
new file mode 100644
index 0000000000000..8b8701810f2e3
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/backspace-icon/index.tsx
@@ -0,0 +1,42 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const BackspaceIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default BackspaceIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/bell-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/bell-icon/index.tsx
new file mode 100644
index 0000000000000..39d316838c64d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/bell-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const BellIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default BellIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/bell-noti-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/bell-noti-icon/index.tsx
new file mode 100644
index 0000000000000..70af40f17f432
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/bell-noti-icon/index.tsx
@@ -0,0 +1,41 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+type IBellNotiIconProps = IconProps & {
+ accentColor?: string
+}
+
+const BellNotiIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ accentColor = "#F43F5E",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default BellNotiIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/bell-off-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/bell-off-icon/index.tsx
new file mode 100644
index 0000000000000..17a30b5a291ec
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/bell-off-icon/index.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const BellOffIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default BellOffIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/buildings-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/buildings-icon/index.tsx
new file mode 100644
index 0000000000000..53f32fe12d32f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/buildings-icon/index.tsx
@@ -0,0 +1,64 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const BuildingsIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default BuildingsIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/cancel-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/cancel-icon/index.tsx
new file mode 100644
index 0000000000000..bfd880882b96b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/cancel-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CancelIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CancelIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/cart-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/cart-icon/index.tsx
new file mode 100644
index 0000000000000..3e8b98f95b5e4
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/cart-icon/index.tsx
@@ -0,0 +1,49 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CartIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+export default CartIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/cash-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/cash-icon/index.tsx
new file mode 100644
index 0000000000000..ffe380bf6d16e
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/cash-icon/index.tsx
@@ -0,0 +1,99 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CashIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CashIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/channels-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/channels-icon.tsx
new file mode 100644
index 0000000000000..37fc735db40a1
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/channels-icon.tsx
@@ -0,0 +1,65 @@
+import React from "react"
+
+import IconProps from "./types/icon-type"
+
+const ChannelsIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ChannelsIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-fill-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-fill-icon/index.tsx
new file mode 100644
index 0000000000000..61d2268599354
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-fill-icon/index.tsx
@@ -0,0 +1,28 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CheckCircleFillIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CheckCircleFillIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-icon/index.tsx
new file mode 100644
index 0000000000000..05fd4dcf3cc2c
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/check-circle-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CheckCircleIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CheckCircleIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/check-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/check-icon.tsx
new file mode 100644
index 0000000000000..7e7ccb3009583
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/check-icon.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const CheckIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CheckIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-down.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-down.tsx
new file mode 100644
index 0000000000000..5af31d7ddea63
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-down.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const ChevronDownIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ChevronDownIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-left-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-left-icon/index.tsx
new file mode 100644
index 0000000000000..469065c6818a2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-left-icon/index.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ChevronLeftIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ChevronLeftIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-right-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-right-icon/index.tsx
new file mode 100644
index 0000000000000..fad3f02718f56
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-right-icon/index.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ChevronRightIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ChevronRightIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-up.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-up.tsx
new file mode 100644
index 0000000000000..750baa77a1d51
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/chevron-up.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const ChevronUpIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ChevronUpIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/clipboard-copy-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/clipboard-copy-icon/index.tsx
new file mode 100644
index 0000000000000..c2ad4311f7f0c
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/clipboard-copy-icon/index.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ClipboardCopyIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ClipboardCopyIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/clock-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/clock-icon/index.tsx
new file mode 100644
index 0000000000000..14996231bd987
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/clock-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ClockIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ClockIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/coins-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/coins-icon/index.tsx
new file mode 100644
index 0000000000000..02225c60bda79
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/coins-icon/index.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CoinsIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CoinsIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/corner-down-right-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/corner-down-right-icon/index.tsx
new file mode 100644
index 0000000000000..7ad7aecc7ab42
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/corner-down-right-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CornerDownRightIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CornerDownRightIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/cross-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/cross-icon/index.tsx
new file mode 100644
index 0000000000000..aaeda63ad569a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/cross-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CrossIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CrossIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/crosshair-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/crosshair-icon/index.tsx
new file mode 100644
index 0000000000000..77c14e9ccb2b2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/crosshair-icon/index.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CrosshairIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CrosshairIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/customer-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/customer-icon/index.tsx
new file mode 100644
index 0000000000000..6c1cdd49df425
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/customer-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const CustomerIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default CustomerIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/details-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/details-icon.tsx
new file mode 100644
index 0000000000000..d0905c0798921
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/details-icon.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const DetailsIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default DetailsIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/discord-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/discord-icon.tsx
new file mode 100644
index 0000000000000..ee6fa5d3c99a0
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/discord-icon.tsx
@@ -0,0 +1,26 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const DiscordIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default DiscordIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/dollar-sign-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/dollar-sign-icon/index.tsx
new file mode 100644
index 0000000000000..7174e441bbaf1
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/dollar-sign-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const DollarSignIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default DollarSignIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/down-left/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/down-left/index.tsx
new file mode 100644
index 0000000000000..657b3944c9616
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/down-left/index.tsx
@@ -0,0 +1,34 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const DownLeftIcon: React.FC = ({
+ size = "16",
+ color = "#9CA3AF",
+}) => {
+ return (
+
+ )
+}
+
+export default DownLeftIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/download-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/download-icon.tsx
new file mode 100644
index 0000000000000..9a76b151112f0
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/download-icon.tsx
@@ -0,0 +1,42 @@
+import React, { FC } from "react"
+import IconProps from "./types/icon-type"
+
+const DownloadIcon: FC = (props) => {
+ const { fill, size, ...attributes } = props
+ const line = fill || "#111827"
+
+ return (
+
+ )
+}
+
+export default DownloadIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/duplicate-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/duplicate-icon.tsx
new file mode 100644
index 0000000000000..d18ef78cdac74
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/duplicate-icon.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const DuplicateIcon: React.FC = ({
+ size = "20px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default DuplicateIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon.tsx
new file mode 100644
index 0000000000000..55a5ff1047e02
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const EditIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default EditIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon/index.tsx
new file mode 100644
index 0000000000000..bad0f3bbc8a7b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/edit-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const EditIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default EditIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/export-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/export-icon/index.tsx
new file mode 100644
index 0000000000000..ee097067dcaf0
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/export-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ExportIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ExportIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/eye-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/eye-icon/index.tsx
new file mode 100644
index 0000000000000..4c9707aa18f8e
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/eye-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const EyeIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default EyeIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/eye-off-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/eye-off-icon/index.tsx
new file mode 100644
index 0000000000000..7f5e19f367439
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/eye-off-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const EyeOffIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default EyeOffIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/fast-delivery-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/fast-delivery-icon/index.tsx
new file mode 100644
index 0000000000000..91a5386fb5e0a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/fast-delivery-icon/index.tsx
@@ -0,0 +1,64 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const FastDeliveryIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default FastDeliveryIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/file-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/file-icon.tsx
new file mode 100644
index 0000000000000..e3e8f43b80506
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/file-icon.tsx
@@ -0,0 +1,55 @@
+import React, { FC } from "react"
+import IconProps from "./types/icon-type"
+
+const FileIcon: FC = (props) => {
+ const { fill, size, ...attributes } = props
+ const line = fill || "#2DD4BF"
+ return (
+
+ )
+}
+
+export default FileIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/gear-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/gear-icon/index.tsx
new file mode 100644
index 0000000000000..b44072f9f8c01
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/gear-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const GearIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default GearIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/gift-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/gift-icon/index.tsx
new file mode 100644
index 0000000000000..dcbdcb16b7ab1
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/gift-icon/index.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const GiftIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default GiftIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/grip-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/grip-icon.tsx
new file mode 100644
index 0000000000000..59ec878fae05a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/grip-icon.tsx
@@ -0,0 +1,64 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const GripIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default GripIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/happy-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/happy-icon/index.tsx
new file mode 100644
index 0000000000000..37b8ac558fd59
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/happy-icon/index.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const HappyIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default HappyIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/help-circle.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/help-circle.tsx
new file mode 100644
index 0000000000000..3d8246e2e4e3a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/help-circle.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const HelpCircleIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default HelpCircleIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/image-placeholder-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/image-placeholder-icon/index.tsx
new file mode 100644
index 0000000000000..c63780bf6254f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/image-placeholder-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ImagePlaceholderIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ImagePlaceholderIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/info-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/info-icon/index.tsx
new file mode 100644
index 0000000000000..723aca577e7b7
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/info-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const InfoIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default InfoIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/key-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/key-icon.tsx
new file mode 100644
index 0000000000000..c70ad4833708f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/key-icon.tsx
@@ -0,0 +1,30 @@
+import React from "react"
+
+import IconProps from "./types/icon-type"
+
+const KeyIcon: React.FC = ({
+ size = "32px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default KeyIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/list-arrow-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/list-arrow-icon/index.tsx
new file mode 100644
index 0000000000000..03a2f2950a30f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/list-arrow-icon/index.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const ListArrowIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ListArrowIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/list-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/list-icon.tsx
new file mode 100644
index 0000000000000..f9eb384900ada
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/list-icon.tsx
@@ -0,0 +1,64 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const ListIcon: React.FC = ({
+ size = "20px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default ListIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/lock-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/lock-icon/index.tsx
new file mode 100644
index 0000000000000..16f15eaea175a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/lock-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const LockIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default LockIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/log-out-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/log-out-icon/index.tsx
new file mode 100644
index 0000000000000..0f7038ac1d1e9
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/log-out-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const SignOutIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default SignOutIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/long-arrow-right-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/long-arrow-right-icon/index.tsx
new file mode 100644
index 0000000000000..4d486d3ed0ac7
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/long-arrow-right-icon/index.tsx
@@ -0,0 +1,38 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const LongArrowRightIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ const width = +size * 2
+
+ return (
+
+ )
+}
+
+export default LongArrowRightIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/mail-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/mail-icon/index.tsx
new file mode 100644
index 0000000000000..8f87867fa81e9
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/mail-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const MailIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default MailIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/map-pin-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/map-pin-icon/index.tsx
new file mode 100644
index 0000000000000..33edfff80593d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/map-pin-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const MapPinIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default MapPinIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/medusa-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/medusa-icon/index.tsx
new file mode 100644
index 0000000000000..aede6fea446a2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/medusa-icon/index.tsx
@@ -0,0 +1,23 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const MedusaIcon: React.FC = ({ size = "48", ...attributes }) => {
+ const width = +size * 0.9375 // width relative to height (from size prop)
+ return (
+
+ )
+}
+
+export default MedusaIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/medusa-vice/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/medusa-vice/index.tsx
new file mode 100644
index 0000000000000..37a198f1fe72d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/medusa-vice/index.tsx
@@ -0,0 +1,39 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const MedusaVice: React.FC = ({
+ size = "96",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default MedusaVice
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/minus-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/minus-icon/index.tsx
new file mode 100644
index 0000000000000..6ec583f91b36f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/minus-icon/index.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const MinusIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default MinusIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/more-horizontal-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/more-horizontal-icon.tsx
new file mode 100644
index 0000000000000..eeee2d1ac7bc9
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/more-horizontal-icon.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const MoreHorizontalIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default MoreHorizontalIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/package-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/package-icon/index.tsx
new file mode 100644
index 0000000000000..dcbfbe5a3b0fe
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/package-icon/index.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const PackageIcon: React.FC = ({
+ size = "16",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default PackageIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/percent-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/percent-icon/index.tsx
new file mode 100644
index 0000000000000..3fab474b91233
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/percent-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const PercentIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default PercentIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/plus-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/plus-icon/index.tsx
new file mode 100644
index 0000000000000..f62578a31d430
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/plus-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const PlusIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default PlusIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/pointer-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/pointer-icon/index.tsx
new file mode 100644
index 0000000000000..2eb7885f416da
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/pointer-icon/index.tsx
@@ -0,0 +1,35 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const PointerIcon: React.FC = ({
+ size = "16",
+ color = "#9CA3AF",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default PointerIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/publish-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/publish-icon/index.tsx
new file mode 100644
index 0000000000000..39b9537bb6d03
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/publish-icon/index.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const PublishIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default PublishIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/refresh-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/refresh-icon.tsx
new file mode 100644
index 0000000000000..a6d2e052d2655
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/refresh-icon.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const RefreshIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default RefreshIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/refund.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/refund.tsx
new file mode 100644
index 0000000000000..bc9127e63ce3d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/refund.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const RefundIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default RefundIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/sad-face-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/sad-face-icon/index.tsx
new file mode 100644
index 0000000000000..62053bfe0a501
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/sad-face-icon/index.tsx
@@ -0,0 +1,51 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const SadFaceIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+
+ )
+}
+
+export default SadFaceIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/sale-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/sale-icon/index.tsx
new file mode 100644
index 0000000000000..9eebba0b27b44
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/sale-icon/index.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const SaleIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default SaleIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/search-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/search-icon/index.tsx
new file mode 100644
index 0000000000000..1c88da425d723
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/search-icon/index.tsx
@@ -0,0 +1,27 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const SearchIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default SearchIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/send-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/send-icon/index.tsx
new file mode 100644
index 0000000000000..50a48367123b7
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/send-icon/index.tsx
@@ -0,0 +1,33 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const SendIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default SendIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/sided-mouth-face/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/sided-mouth-face/index.tsx
new file mode 100644
index 0000000000000..2448795b60dd2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/sided-mouth-face/index.tsx
@@ -0,0 +1,51 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const SidedMouthFaceIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default SidedMouthFaceIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/sorting-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/sorting-icon/index.tsx
new file mode 100644
index 0000000000000..ba6912b2fb232
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/sorting-icon/index.tsx
@@ -0,0 +1,54 @@
+import clsx from "clsx"
+import React from "react"
+import IconProps from "../types/icon-type"
+
+type SortingIconProps = {
+ ascendingColor?: string
+ descendingColor?: string
+ isSorted?: "asc" | "desc" | false
+} & IconProps
+
+const SortingIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ascendingColor,
+ descendingColor,
+ isSorted = false,
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default SortingIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/sparkles-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/sparkles-icon/index.tsx
new file mode 100644
index 0000000000000..5b33d75e1f989
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/sparkles-icon/index.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const SparklesIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default SparklesIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/stop-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/stop-icon.tsx
new file mode 100644
index 0000000000000..90f790a8c9684
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/stop-icon.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const StopIcon: React.FC = ({
+ size = "20px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default StopIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/tag-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/tag-icon/index.tsx
new file mode 100644
index 0000000000000..7cbfd29a5b645
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/tag-icon/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const TagIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default TagIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/taxes-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/taxes-icon.tsx
new file mode 100644
index 0000000000000..13bd2a3dc4adb
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/taxes-icon.tsx
@@ -0,0 +1,54 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const TaxesIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default TaxesIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/tile-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/tile-icon.tsx
new file mode 100644
index 0000000000000..2fd60da800c3b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/tile-icon.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const TileIcon: React.FC = ({
+ size = "20px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default TileIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/trash-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/trash-icon.tsx
new file mode 100644
index 0000000000000..ac951b00ed31f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/trash-icon.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const TrashIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default TrashIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/triangle-right-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/triangle-right-icon/index.tsx
new file mode 100644
index 0000000000000..a77d54b4f7bd6
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/triangle-right-icon/index.tsx
@@ -0,0 +1,28 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const TriangleRightIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default TriangleRightIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/truck-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/truck-icon/index.tsx
new file mode 100644
index 0000000000000..880efb9139928
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/truck-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const TruckIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default TruckIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/types/icon-type.ts b/packages/admin-ui/ui/src/components/fundamentals/icons/types/icon-type.ts
new file mode 100644
index 0000000000000..782681a462220
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/types/icon-type.ts
@@ -0,0 +1,8 @@
+import React from "react"
+
+type IconProps = {
+ color?: string
+ size?: string | number
+} & React.SVGAttributes
+
+export default IconProps
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/u-turn-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/u-turn-icon.tsx
new file mode 100644
index 0000000000000..57a9ce98b0857
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/u-turn-icon.tsx
@@ -0,0 +1,29 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const UTurnIcon: React.FC = ({
+ size = "20px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default UTurnIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/unpublish-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/unpublish-icon/index.tsx
new file mode 100644
index 0000000000000..c33da151df7cb
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/unpublish-icon/index.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const UnpublishIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default UnpublishIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/upload-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/upload-icon/index.tsx
new file mode 100644
index 0000000000000..5557b92cd6de4
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/upload-icon/index.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const UploadIcon: React.FC = ({
+ size = "20",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default UploadIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/users-icon/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/users-icon/index.tsx
new file mode 100644
index 0000000000000..9665bb52b73de
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/users-icon/index.tsx
@@ -0,0 +1,50 @@
+import React from "react"
+import IconProps from "../types/icon-type"
+
+const UsersIcon: React.FC = ({
+ size = "24",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default UsersIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/warning-circle.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/warning-circle.tsx
new file mode 100644
index 0000000000000..d97d275068a90
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/warning-circle.tsx
@@ -0,0 +1,42 @@
+import React, { FC } from "react"
+import IconProps from "./types/icon-type"
+
+const WarningCircle: FC = (props) => {
+ const { fill, size, ...attributes } = props
+ const line = fill || "#111827"
+
+ return (
+
+ )
+}
+
+export default WarningCircle
diff --git a/packages/admin-ui/ui/src/components/fundamentals/icons/x-circle-icon.tsx b/packages/admin-ui/ui/src/components/fundamentals/icons/x-circle-icon.tsx
new file mode 100644
index 0000000000000..318327a76a383
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/icons/x-circle-icon.tsx
@@ -0,0 +1,43 @@
+import React from "react"
+import IconProps from "./types/icon-type"
+
+const XCircleIcon: React.FC = ({
+ size = "24px",
+ color = "currentColor",
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default XCircleIcon
diff --git a/packages/admin-ui/ui/src/components/fundamentals/image-placeholder.tsx b/packages/admin-ui/ui/src/components/fundamentals/image-placeholder.tsx
new file mode 100644
index 0000000000000..a6d7b7b2dc429
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/image-placeholder.tsx
@@ -0,0 +1,11 @@
+import ImagePlaceholderIcon from "./icons/image-placeholder-icon"
+
+const ImagePlaceholder = () => {
+ return (
+
+
+
+ )
+}
+
+export default ImagePlaceholder
diff --git a/packages/admin-ui/ui/src/components/fundamentals/input-container.tsx b/packages/admin-ui/ui/src/components/fundamentals/input-container.tsx
new file mode 100644
index 0000000000000..81464a3a3cdc1
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/input-container.tsx
@@ -0,0 +1,37 @@
+import clsx from "clsx"
+import React, { MouseEventHandler } from "react"
+
+type InputContainerProps = React.HTMLAttributes & {
+ className?: string
+ onClick?: MouseEventHandler
+ onFocusLost?: () => void
+}
+
+const InputContainer: React.FC = ({
+ onClick,
+ onFocusLost,
+ children,
+ className,
+ ...props
+}) => {
+ return (
+ {
+ if (onFocusLost && !e.currentTarget.contains(e.relatedTarget)) {
+ onFocusLost()
+ }
+ }}
+ className={clsx([
+ `bg-grey-5 inter-base-regular w-full p-3 flex h-18 flex-col cursor-text border border-grey-20 focus-within:shadow-input focus-within:border-violet-60 rounded-rounded`,
+ className,
+ ])}
+ >
+ {children}
+
+ )
+}
+
+export default InputContainer
diff --git a/packages/admin-ui/ui/src/components/fundamentals/input-header.tsx b/packages/admin-ui/ui/src/components/fundamentals/input-header.tsx
new file mode 100644
index 0000000000000..c2bc79296fc78
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/input-header.tsx
@@ -0,0 +1,38 @@
+import clsx from "clsx"
+import React from "react"
+import IconTooltip from "../molecules/icon-tooltip"
+
+export type InputHeaderProps = {
+ label?: string
+ required?: boolean
+ tooltipContent?: string
+ tooltip?: React.ReactNode
+ className?: string
+}
+
+const InputHeader: React.FC = ({
+ label,
+ required = false,
+ tooltipContent,
+ tooltip,
+ className,
+}) => {
+ return (
+
+
+ {required &&
*
}
+ {tooltip || tooltipContent ? (
+
+ {tooltip || }
+
+ ) : null}
+
+ )
+}
+
+export default InputHeader
diff --git a/packages/admin-ui/ui/src/components/fundamentals/status-indicator/index.tsx b/packages/admin-ui/ui/src/components/fundamentals/status-indicator/index.tsx
new file mode 100644
index 0000000000000..4a2993cd01157
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/fundamentals/status-indicator/index.tsx
@@ -0,0 +1,34 @@
+import clsx from "clsx"
+import React from "react"
+
+type StatusIndicatorProps = {
+ title?: string
+ variant: "primary" | "danger" | "warning" | "success" | "active" | "default"
+} & React.HTMLAttributes
+
+const StatusIndicator: React.FC = ({
+ title,
+ variant = "success",
+ className,
+ ...props
+}) => {
+ const dotClass = clsx({
+ "bg-teal-50": variant === "success",
+ "bg-rose-50": variant === "danger",
+ "bg-yellow-50": variant === "warning",
+ "bg-violet-60": variant === "primary",
+ "bg-emerald-40": variant === "active",
+ "bg-grey-40": variant === "default",
+ })
+ return (
+
+ )
+}
+
+export default StatusIndicator
diff --git a/packages/admin-ui/ui/src/components/molecules/actionables.tsx b/packages/admin-ui/ui/src/components/molecules/actionables.tsx
new file mode 100644
index 0000000000000..9a883ba65cf12
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/actionables.tsx
@@ -0,0 +1,115 @@
+import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
+import clsx from "clsx"
+import React from "react"
+import Button from "../fundamentals/button"
+import MoreHorizontalIcon from "../fundamentals/icons/more-horizontal-icon"
+
+export type ActionType = {
+ label: string
+ onClick: (e: React.MouseEvent) => void
+ variant?: "normal" | "danger"
+ disabled?: boolean
+ icon?: React.ReactNode
+}
+
+type ActionablesProps = {
+ actions?: ActionType[]
+ customTrigger?: React.ReactNode
+ forceDropdown?: boolean
+}
+
+const Actionables: React.FC = ({
+ actions,
+ customTrigger,
+ forceDropdown = false,
+}) => {
+ if (actions && (forceDropdown || actions.length > 1)) {
+ return (
+
+
+
+ {!customTrigger ? (
+
+ ) : (
+ customTrigger
+ )}
+
+
+
+ {actions.map((action, i) => {
+ return (
+
+ {
+
+ }
+
+ )
+ })}
+
+
+
+ )
+ }
+
+ if (customTrigger) {
+ const triggers = Array.isArray(customTrigger)
+ ? customTrigger
+ : [customTrigger]
+ return (
+
+ {triggers.map((trigger, i) => (
+
{trigger}
+ ))}
+
+ )
+ }
+
+ const [action] = actions ?? []
+ if (action) {
+ return (
+
+
+
+ )
+ }
+
+ return null
+}
+
+export default Actionables
diff --git a/packages/admin-ui/ui/src/components/molecules/activity-card/index.tsx b/packages/admin-ui/ui/src/components/molecules/activity-card/index.tsx
new file mode 100644
index 0000000000000..adab095cfabd7
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/activity-card/index.tsx
@@ -0,0 +1,88 @@
+import React, { MutableRefObject, ReactNode } from "react"
+import StatusIndicator from "../../fundamentals/status-indicator"
+import Tooltip from "../../atoms/tooltip"
+import clsx from "clsx"
+
+export type ActivityCardProps = {
+ key?: string
+ title: string
+ icon?: ReactNode
+ relativeTimeElapsed?: string
+ date?: string | Date
+ shouldShowStatus?: boolean
+ children?: ReactNode[]
+}
+
+export const ActivityCard: React.FC = (
+ props: ActivityCardProps
+) => {
+ const {
+ key,
+ title,
+ icon,
+ relativeTimeElapsed,
+ shouldShowStatus,
+ children
+ } = props
+
+ const date = !!props.date && new Date(props.date).toLocaleDateString(
+ "en-us",
+ {
+ hour12: true,
+ day: "2-digit",
+ month: "short",
+ hour: "numeric",
+ minute: "numeric",
+ second: "numeric",
+ })
+ const formattedDate = !!date && date.replace(",", " at")
+
+ const getTimeElement = () => {
+ return (
+
+ {
+ !!relativeTimeElapsed && (
+ {relativeTimeElapsed}
+ )
+ }
+ {
+ shouldShowStatus &&
+
+ }
+
+ )
+ }
+
+ return (
+
+
+
+
+
+ {
+ !!icon && icon
+ }
+ {title}
+
+
+ {
+ ((!!relativeTimeElapsed || shouldShowStatus)) && (
+ formattedDate ? (
+
+ {getTimeElement()}
+
+ ) : (
+ getTimeElement()
+ )
+ )
+ }
+
+
+
+ {children}
+
+
+
+
+ )
+}
diff --git a/packages/admin-ui/ui/src/components/molecules/amount-input/amount-and-currency-input.tsx b/packages/admin-ui/ui/src/components/molecules/amount-input/amount-and-currency-input.tsx
new file mode 100644
index 0000000000000..8926d613632e5
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/amount-input/amount-and-currency-input.tsx
@@ -0,0 +1,134 @@
+import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
+import AmountField from "react-currency-input-field"
+import { Option } from "../../../types/shared"
+import { currencies } from "../../../utils/currencies"
+import InputError from "../../atoms/input-error"
+import InputHeader from "../../fundamentals/input-header"
+import { NextSelect } from "../select/next-select"
+
+type Value = {
+ amount: number | null | undefined
+ currency: Option | null | undefined
+}
+
+type Props = {
+ label?: string
+ errors?: Record
+ name?: string
+ onChange: (value: Value) => void
+ onBlur?: React.FocusEventHandler
+ value: Value
+}
+
+const AmountAndCurrencyInput = ({
+ label,
+ errors,
+ name,
+ value,
+ onChange,
+ onBlur,
+}: Props) => {
+ const { symbol_native, decimal_digits } = useMemo(() => {
+ let symbol_native = "$"
+ let decimal_digits = 2
+
+ if (value.currency) {
+ const currency = currencies[value.currency.value.toUpperCase()]
+
+ symbol_native = currency.symbol_native
+ decimal_digits = currency.decimal_digits
+ }
+
+ return { symbol_native, decimal_digits }
+ }, [value])
+
+ const step = useMemo(() => 10 ** -decimal_digits, [decimal_digits])
+
+ const getFormattedValue = useCallback(
+ (value: number) => {
+ return `${value / 10 ** decimal_digits}`
+ },
+ [decimal_digits]
+ )
+
+ const [formattedValue, setFormattedValue] = useState(
+ value.amount !== undefined && value.amount !== null
+ ? getFormattedValue(value.amount)
+ : undefined
+ )
+
+ const inputRef = useRef(null)
+
+ /**
+ * Update the amount when the decimal digits change
+ */
+ useEffect(() => {
+ inputRef.current?.dispatchEvent(new Event("blur"))
+ }, [decimal_digits])
+
+ const onCurrencyChange = (currency?: Option | null) => {
+ onChange({ amount: value.amount, currency: currency })
+ }
+
+ /**
+ * On amount change, update the amount and formatted value.
+ * The amount passed to the onChange function is the DB persisted value,
+ * the formatted value is the value that is displayed in the input.
+ */
+ const onAmountChange = (amount?: string, floatValue?: number | null) => {
+ let numericalValue: number | null | undefined = 0
+
+ if (floatValue) {
+ numericalValue = Math.round(floatValue * 10 ** decimal_digits)
+ }
+
+ onChange({ amount: numericalValue, currency: value.currency })
+ setFormattedValue(amount)
+ }
+
+ return (
+
+ {label &&
}
+
+
+
({
+ value: c.code,
+ label: c.code,
+ }))}
+ isMulti={false}
+ onBlur={onBlur}
+ value={value.currency}
+ onChange={onCurrencyChange}
+ />
+
+
+ onAmountChange(value, values?.float)
+ }
+ allowNegativeValue={false}
+ placeholder="-"
+ decimalScale={decimal_digits}
+ className="bg-transparent outline-none outline-0 w-full remove-number-spinner leading-base text-grey-90 font-normal caret-violet-60 placeholder-grey-40 text-right"
+ />
+
+
+
+
+
+
+ )
+}
+
+export default AmountAndCurrencyInput
diff --git a/packages/admin-ui/ui/src/components/molecules/amount-input/amount-input.tsx b/packages/admin-ui/ui/src/components/molecules/amount-input/amount-input.tsx
new file mode 100644
index 0000000000000..b746e272e5dfe
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/amount-input/amount-input.tsx
@@ -0,0 +1,92 @@
+import clsx from "clsx"
+import React, { useEffect, useState } from "react"
+import AmountField from "react-currency-input-field"
+import { currencies } from "../../../utils/currencies"
+import InputError from "../../atoms/input-error"
+import InputHeader from "../../fundamentals/input-header"
+
+type Props = {
+ currencyCode: string
+ value?: number | null
+ onChange: (amount?: number | null) => void
+ errors?: { [x: string]: unknown }
+ name?: string
+ label?: string
+}
+
+const AmountInput = ({
+ name,
+ label,
+ currencyCode,
+ errors,
+ value,
+ onChange,
+}: Props) => {
+ const { symbol_native, decimal_digits } = currencies[
+ currencyCode.toUpperCase()
+ ]
+
+ const getFormattedValue = (value: number) => {
+ return `${value / 10 ** decimal_digits}`
+ }
+
+ const [formattedValue, setFormattedValue] = useState(
+ value !== undefined && value !== null ? getFormattedValue(value) : undefined
+ )
+
+ useEffect(() => {
+ if (value) {
+ setFormattedValue(getFormattedValue(value))
+ }
+ }, [value, decimal_digits])
+
+ const onAmountChange = (value?: string, floatValue?: number | null) => {
+ if (floatValue) {
+ const numericalValue = Math.round(floatValue * 10 ** decimal_digits)
+ onChange(numericalValue)
+ } else {
+ onChange(0)
+ }
+ setFormattedValue(value)
+ }
+
+ const step = 10 ** -decimal_digits
+
+ return (
+
+ {label &&
}
+
+
+
{currencyCode.toUpperCase()}
+
+
+
+
+ onAmountChange(value, values?.float)
+ }
+ allowNegativeValue={false}
+ placeholder="-"
+ decimalScale={decimal_digits}
+ className="bg-transparent outline-none outline-0 w-full remove-number-spinner leading-base text-grey-90 font-normal caret-violet-60 placeholder-grey-40 text-right"
+ />
+
+
+
+
+
+ )
+}
+
+export default AmountInput
diff --git a/packages/admin-ui/ui/src/components/molecules/amount-input/index.ts b/packages/admin-ui/ui/src/components/molecules/amount-input/index.ts
new file mode 100644
index 0000000000000..107e86ddd8f7a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/amount-input/index.ts
@@ -0,0 +1,4 @@
+import AmountAndCurrencyInput from "./amount-and-currency-input"
+import AmountInput from "./amount-input"
+
+export { AmountAndCurrencyInput, AmountInput }
diff --git a/packages/admin-ui/ui/src/components/molecules/availability-duration/index.tsx b/packages/admin-ui/ui/src/components/molecules/availability-duration/index.tsx
new file mode 100644
index 0000000000000..bf62a87080706
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/availability-duration/index.tsx
@@ -0,0 +1,86 @@
+import { parse } from "iso8601-duration"
+import React, { useEffect, useState } from "react"
+import InputField from "../input"
+
+type AvailabilityDurationProps = {
+ onChange: React.Dispatch>
+ value: string | undefined
+}
+
+const getValue = (e: React.ChangeEvent) =>
+ parseFloat(e.target.value)
+
+const AvailabilityDuration: React.FC = ({
+ value,
+ onChange,
+}) => {
+ const duration = value ? parse(value) : {}
+ const [durationYears, setDurationYears] = useState(duration.years || 0)
+ const [durationMonths, setDurationMonths] = useState(duration.months || 0)
+ const [durationDays, setDurationDays] = useState(duration.days || 0)
+ const [durationHours, setDurationHours] = useState(duration.hours || 0)
+ const [durationMinutes, setDurationMinutes] = useState(duration.minutes || 0)
+
+ useEffect(() => {
+ const isoString = `P${durationYears || 0}Y${durationMonths || 0}M${
+ durationDays || 0
+ }DT${durationHours || 0}H${durationMinutes || 0}M`
+
+ onChange(isoString)
+ }, [
+ durationYears,
+ durationMonths,
+ durationDays,
+ durationHours,
+ durationMinutes,
+ ])
+
+ return (
+
+
+ setDurationYears(getValue(e))}
+ min={0}
+ />
+ setDurationMonths(getValue(e))}
+ min={0}
+ />
+ setDurationDays(getValue(e))}
+ min={0}
+ />
+ setDurationHours(getValue(e))}
+ min={0}
+ />
+ setDurationMinutes(getValue(e))}
+ min={0}
+ />
+
+
+ )
+}
+
+export default AvailabilityDuration
diff --git a/packages/admin-ui/ui/src/components/molecules/banner-card/index.tsx b/packages/admin-ui/ui/src/components/molecules/banner-card/index.tsx
new file mode 100644
index 0000000000000..8bcf7c316ccca
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/banner-card/index.tsx
@@ -0,0 +1,73 @@
+import React from "react"
+import Actionables, { ActionType } from "../../molecules/actionables"
+
+type BannerCardProps = {
+ actions?: ActionType[]
+ title: string
+ thumbnail: string | null
+} & React.RefAttributes
+
+type BannerCardDescriptionProps = {
+ cta?: {
+ label: string
+ onClick: (e: React.MouseEvent) => void
+ }
+}
+
+const BannerCard: React.FC & {
+ Description: React.FC
+ Footer: React.FC
+} = ({ title, thumbnail, actions, children }) => {
+ return (
+
+
+ {thumbnail && (
+
+

+
+ )}
+
+
+
+ )
+}
+
+const Description: React.FC = ({
+ cta,
+ children,
+}) => {
+ return (
+
+
+ {children}
+
+ {cta && (
+
+ )}
+
+ )
+}
+
+const Footer: React.FC = ({ children }) => {
+ return {children}
+}
+
+BannerCard.Description = Description
+BannerCard.Footer = Footer
+
+export default BannerCard
diff --git a/packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx b/packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx
new file mode 100644
index 0000000000000..850341bba7f9b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/batch-job-file-card/index.tsx
@@ -0,0 +1,42 @@
+import React, { ReactNode } from "react"
+
+type Props = {
+ fileName: string
+ fileSize?: string
+ icon?: ReactNode
+ onClick?: () => void
+}
+
+const BatchJobFileCard = ({ fileName, fileSize, icon, onClick }: Props) => {
+ const preparedOnClick = (onClick ?? (() => void 0))
+
+ return (
+
+
+ {!!icon && icon}
+
+
+
+
+ {fileName}
+
+
+ {!!fileSize && (
+
+ {fileSize}
+
+ )}
+
+
+ )
+}
+
+export default BatchJobFileCard
diff --git a/packages/admin-ui/ui/src/components/molecules/breadcrumb/index.tsx b/packages/admin-ui/ui/src/components/molecules/breadcrumb/index.tsx
new file mode 100644
index 0000000000000..7acb5dd2683bf
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/breadcrumb/index.tsx
@@ -0,0 +1,42 @@
+import clsx from "clsx"
+import React from "react"
+import { useNavigate } from "react-router-dom"
+import ChevronRightIcon from "../../fundamentals/icons/chevron-right-icon"
+
+type BreadcrumbProps = React.HtmlHTMLAttributes & {
+ previousRoute?: string
+ previousBreadcrumb?: string
+ currentPage: string
+}
+
+const Breadcrumb: React.FC = ({
+ previousRoute = "/a/settings",
+ previousBreadcrumb = "Settings",
+ currentPage,
+ className,
+ ...props
+}) => {
+ const navigate = useNavigate()
+ return (
+
+ navigate(previousRoute)}
+ >
+ {previousBreadcrumb}
+
+
+
+
+ {currentPage}
+
+ )
+}
+
+export default Breadcrumb
diff --git a/packages/admin-ui/ui/src/components/molecules/collapsible-tree/index.tsx b/packages/admin-ui/ui/src/components/molecules/collapsible-tree/index.tsx
new file mode 100644
index 0000000000000..13a48de7c528c
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/collapsible-tree/index.tsx
@@ -0,0 +1,187 @@
+import React from "react"
+import clsx from "clsx"
+
+import MoreHorizontalIcon from "../../fundamentals/icons/more-horizontal-icon"
+import MinusIcon from "../../fundamentals/icons/minus-icon"
+import PlusIcon from "../../fundamentals/icons/plus-icon"
+import Button from "../../fundamentals/button"
+import Actionables, { ActionType } from "../actionables"
+
+/* ---------------------------- CollapsibleTree ------------------------------------ */
+
+type CollapsibleTreeType = React.FC & {
+ Parent: React.FC
+ Leaf: React.FC
+ Content: React.FC
+}
+
+type TCollapsibleTreeContext = {
+ open: boolean
+ handleOpen: () => void
+ handleClose: () => void
+ toggle: () => void
+}
+
+const CollapsibleTreeContext = React.createContext(
+ null
+)
+
+export const CollapsibleTree: CollapsibleTreeType = ({ children }) => {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+ setOpen(true),
+ handleClose: () => setOpen(false),
+ toggle: () => setOpen((open) => !open),
+ }}
+ >
+ {children}
+
+ )
+}
+
+CollapsibleTreeContext.displayName = "CollapsibleTreeContext"
+
+const useCollapsibleTree = () => {
+ const context = React.useContext(CollapsibleTreeContext)
+ if (!context) {
+ throw new Error("useCollapsibleTree must be a child of CollapsibleTree")
+ }
+ return context
+}
+
+/* ---------------------------- CollapsibleTreeContent ------------------------------------ */
+
+type CollapsibleTreeContentProps = React.HTMLAttributes
+
+const CollapsibleTreeContent: React.FC = ({
+ children,
+ className,
+ ...props
+}) => {
+ const { open } = useCollapsibleTree()
+ return (
+
+ {children}
+
+ )
+}
+
+CollapsibleTree.Content = CollapsibleTreeContent
+
+/* ---------------------------- CollapsibleTreeParent ------------------------------------ */
+
+type CollapsibleTreeParentProps = {
+ actions?: ActionType[]
+ className?: string
+}
+
+const CollapsibleTreeParent: React.FC = ({
+ actions,
+ className,
+ children,
+}) => {
+ const { open, toggle } = useCollapsibleTree()
+ return (
+
+
+
+
{children}
+
+ {actions && (
+
+ )}
+
+
+
+
+
+
+ )
+}
+
+CollapsibleTree.Parent = CollapsibleTreeParent
+
+/* ---------------------------- CollapsibleTreeLeaf ------------------------------------ */
+
+type CollapsibleTreeLeafProps = {
+ actions?: ActionType[]
+ className?: string
+}
+
+const CollapsibleTreeLeaf: React.FC = ({
+ className,
+ children,
+ actions,
+}) => {
+ return (
+
+
+
+
+ {children}
+ {actions && (
+
+ )}
+
+
+ )
+}
+
+CollapsibleTree.Leaf = CollapsibleTreeLeaf
+
+const Container: React.FC<{ className?: string }> = ({
+ children,
+ className,
+}) => {
+ return (
+
+ {children}
+
+ )
+}
+
+const Trigger = () => {
+ return (
+
+ )
+}
diff --git a/packages/admin-ui/ui/src/components/molecules/connected-form.tsx b/packages/admin-ui/ui/src/components/molecules/connected-form.tsx
new file mode 100644
index 0000000000000..7242ee5314f3e
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/connected-form.tsx
@@ -0,0 +1,20 @@
+import type { ReactElement } from "react"
+import type { FieldValues, UseFormReturn } from "react-hook-form"
+import { useFormContext } from "react-hook-form"
+
+interface ConnectedFormProps {
+ children(children: UseFormReturn): ReactElement
+}
+
+/**
+ * Utility component for nested forms.
+ */
+const ConnectedForm = ({
+ children,
+}: ConnectedFormProps) => {
+ const methods = useFormContext()
+
+ return children({ ...methods })
+}
+
+export default ConnectedForm
diff --git a/packages/admin-ui/ui/src/components/molecules/customer-avatar-item/index.tsx b/packages/admin-ui/ui/src/components/molecules/customer-avatar-item/index.tsx
new file mode 100644
index 0000000000000..76334c90aeada
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/customer-avatar-item/index.tsx
@@ -0,0 +1,34 @@
+import React from "react"
+import Avatar from "../../atoms/avatar"
+
+type CustomerAvatarItemProps = {
+ color?: string
+ customer: {
+ first_name?: string
+ last_name?: string
+ email: string
+ }
+}
+
+const CustomerAvatarItem: React.FC = ({
+ color = "bg-violet-60",
+ customer,
+}: CustomerAvatarItemProps) => {
+ const identifier =
+ customer.first_name || customer.last_name
+ ? `${customer.first_name} ${customer.last_name}`
+ : customer.email
+ ? customer.email
+ : "-"
+
+ return (
+
+ )
+}
+
+export default CustomerAvatarItem
diff --git a/packages/admin-ui/ui/src/components/molecules/customers-groups-summary/index.tsx b/packages/admin-ui/ui/src/components/molecules/customers-groups-summary/index.tsx
new file mode 100644
index 0000000000000..f797450e75ef2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/customers-groups-summary/index.tsx
@@ -0,0 +1,33 @@
+import { sortBy } from "lodash"
+
+import { CustomerGroup } from "@medusajs/medusa"
+
+/**
+ * Customers Associated Groups props
+ */
+interface P {
+ groups: CustomerGroup[]
+}
+
+/*
+ * Render a summary of groups to which the customer belongs
+ */
+function CustomersGroupsSummary(props: P) {
+ const groups = sortBy(props.groups, "name")
+ if (!groups.length) {
+ return null
+ }
+
+ const left = groups.length - 1
+ const leadName = groups[0].name
+ const allGroups = groups.map((g) => g.name).join(", ")
+
+ return (
+
+ {leadName}
+ {!!left && + {left} more}
+
+ )
+}
+
+export default CustomersGroupsSummary
diff --git a/packages/admin-ui/ui/src/components/molecules/emoji-picker/index.tsx b/packages/admin-ui/ui/src/components/molecules/emoji-picker/index.tsx
new file mode 100644
index 0000000000000..69287233d81f0
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/emoji-picker/index.tsx
@@ -0,0 +1,41 @@
+import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
+import Picker, { EmojiStyle, SkinTones } from "emoji-picker-react"
+import React from "react"
+import Button from "../../fundamentals/button"
+import HappyIcon from "../../fundamentals/icons/happy-icon"
+
+type indexProps = {
+ onEmojiClick: (emoji: string) => void
+}
+
+const EmojiPicker: React.FC = ({ onEmojiClick }) => {
+ return (
+
+
+
+
+
+
+ onEmojiClick(emojiData.emoji)}
+ defaultSkinTone={SkinTones.NEUTRAL}
+ emojiStyle={EmojiStyle.NATIVE}
+ skinTonesDisabled
+ searchPlaceHolder={"Search Emoji..."}
+ />
+
+
+ )
+}
+
+export default EmojiPicker
diff --git a/packages/admin-ui/ui/src/components/molecules/filter-dropdown/container.tsx b/packages/admin-ui/ui/src/components/molecules/filter-dropdown/container.tsx
new file mode 100644
index 0000000000000..1ef51aa675d94
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/filter-dropdown/container.tsx
@@ -0,0 +1,89 @@
+import * as RadixPopover from "@radix-ui/react-popover"
+import React, {
+ PropsWithChildren,
+ ReactNode,
+ useEffect,
+ useRef,
+ useState,
+} from "react"
+import { useWindowDimensions } from "../../../hooks/use-window-dimensions"
+import Button from "../../fundamentals/button"
+
+type FilterDropdownContainerProps = {
+ submitFilters: () => void
+ clearFilters: () => void
+ triggerElement: ReactNode
+}
+
+const FilterDropdownContainer = ({
+ submitFilters,
+ clearFilters,
+ triggerElement,
+ children,
+}: PropsWithChildren) => {
+ const { height } = useWindowDimensions()
+ const ref = useRef(null)
+ const [isOpen, setIsOpen] = useState(false)
+ const [heightStyle, setHeightStyle] = useState({
+ maxHeight: height,
+ })
+
+ useEffect(() => {
+ setHeightStyle({
+ maxHeight: height - (ref?.current?.getBoundingClientRect().y ?? 0) - 50,
+ })
+ }, [ref])
+
+ const onSubmit = () => {
+ setIsOpen(false)
+ submitFilters()
+ }
+
+ const onClear = () => {
+ setIsOpen(false)
+ clearFilters()
+ }
+
+ return (
+
+
+ {triggerElement}
+
+
+
+
+
+
+ {React.Children.map(children, (child) => {
+ return (
+
+ {child}
+
+ )
+ })}
+
+
+ )
+}
+
+export default FilterDropdownContainer
diff --git a/packages/admin-ui/ui/src/components/molecules/filter-dropdown/item.tsx b/packages/admin-ui/ui/src/components/molecules/filter-dropdown/item.tsx
new file mode 100644
index 0000000000000..ea5cbb073a33d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/filter-dropdown/item.tsx
@@ -0,0 +1,551 @@
+import * as RadixCollapsible from "@radix-ui/react-collapsible"
+import * as RadixPopover from "@radix-ui/react-popover"
+import clsx from "clsx"
+import moment from "moment"
+import { useEffect, useMemo, useState } from "react"
+import { DateFilters } from "../../../utils/filters"
+import { addHours, atMidnight, dateToUnixTimestamp } from "../../../utils/time"
+import { CalendarComponent } from "../../atoms/date-picker/date-picker"
+import Spinner from "../../atoms/spinner"
+import ArrowRightIcon from "../../fundamentals/icons/arrow-right-icon"
+import CheckIcon from "../../fundamentals/icons/check-icon"
+import ChevronUpIcon from "../../fundamentals/icons/chevron-up"
+import InputField from "../input"
+
+const DAY_IN_SECONDS = 86400
+
+const FilterDropdownItem = ({
+ filterTitle,
+ options,
+ filters,
+ open,
+ setFilter,
+ isLoading,
+ hasMore,
+ hasPrev,
+ onShowNext,
+ onShowPrev,
+}) => {
+ const prefilled = useMemo(() => {
+ try {
+ const toReturn = filters.reduce((acc, f) => {
+ acc[f] = true
+ return acc
+ }, {})
+ return toReturn
+ } catch (e) {
+ return {}
+ }
+ }, [filters])
+
+ const [checked, setChecked] = useState(prefilled)
+
+ const handlePrev = () => {
+ if (onShowPrev) {
+ onShowPrev()
+ }
+ }
+
+ const handleNext = () => {
+ if (onShowNext) {
+ onShowNext()
+ }
+ }
+
+ useEffect(() => {
+ if (!open) {
+ setChecked({})
+ }
+ }, [open])
+
+ const onCheck = (filter) => {
+ const checkedState = checked
+
+ if (!checkedState[filter]) {
+ checkedState[filter] = true
+ } else {
+ checkedState[filter] = false
+ }
+
+ const newFilter = Object.entries(checkedState).reduce(
+ (acc, [key, value]) => {
+ if (value === true) {
+ acc.push(key)
+ }
+ return acc
+ },
+ []
+ )
+
+ setChecked(checkedState)
+
+ setFilter({ open: open, filter: newFilter })
+ }
+
+ return (
+
+
setFilter({ filter: filters, open })}
+ >
+
+
+
+
+ {open && }
+
+
+
+
{filterTitle}
+
+ {open && (
+
+
+
+ )}
+
+
+ {hasPrev && (
+
+
+
+ )}
+ {isLoading ? (
+
+
+
+ ) : filterTitle === "Date" ? (
+
+ ) : (
+ options.map((el, i) => {
+ let value: string
+ let label: string
+
+ if (typeof el === "string") {
+ value = el
+ label = el
+ } else {
+ value = el.value
+ label = el.label
+ }
+
+ return (
+ onCheck(value)}
+ >
+
+
+ {checked[value] === true && }
+
+
+
+ {label}
+
+ )
+ })
+ )}
+ {hasMore && (
+
+
+
+ )}
+
+
+
+ )
+}
+
+export default FilterDropdownItem
+
+const parseDateFilter = (filter) => {
+ if (!filter) {
+ return {}
+ }
+ const dateEntries = Object.entries(filter)
+
+ /**
+ * From a query object we need to figure out which date filter that is
+ * being used of the following:
+ *
+ * InTheLast: { gt: "x|[days|months]" }
+ * OlderThan: { lt: "x|[days|months]" }
+ * Between: { lt: [ts], gt: [ts] }
+ * After: { gt: [ts] }
+ * Before: { lt: [ts] },
+ * EqualTo: { lt: [midnight], gt: [morning] }
+ *
+ */
+
+ const flags = {
+ sawGt: false,
+ sawLt: false,
+ sawGtRelative: false,
+ sawLtRelative: false,
+ }
+
+ for (const [key, value] of dateEntries) {
+ switch (key) {
+ case "gt": {
+ flags.sawGt = true
+ flags.sawGtRelative = value.includes("|")
+ break
+ }
+ case "lt": {
+ flags.sawLt = true
+ flags.sawLtRelative = value.includes("|")
+ break
+ }
+ default: {
+ break
+ }
+ }
+ }
+
+ if (flags.sawGt && flags.sawGtRelative) {
+ const [amount, daysMonths] = filter.gt.split("|")
+ return {
+ filterType: DateFilters.InTheLast,
+ daysMonthsValue: daysMonths,
+ relativeAmount: amount,
+ value: null,
+ }
+ }
+
+ if (flags.sawLt && flags.sawLtRelative) {
+ const [amount, daysMonths] = filter.lt.split("|")
+ return {
+ filterType: DateFilters.OlderThan,
+ daysMonthsValue: daysMonths,
+ relativeAmount: amount,
+ value: null,
+ }
+ }
+
+ if (flags.sawLt && flags.sawGt) {
+ const startDate = filter.gt
+ const endDate = filter.lt
+
+ if (endDate - startDate === DAY_IN_SECONDS) {
+ return {
+ filterType: DateFilters.EqualTo,
+ value: moment.unix(startDate).toDate(),
+ }
+ }
+ }
+
+ if (flags.sawLt) {
+ const endDate = filter.lt
+ return {
+ filterType: DateFilters.Before,
+ value: moment.unix(endDate).toDate(),
+ }
+ }
+
+ if (flags.sawGt) {
+ const startDate = filter.gt
+ return {
+ filterType: DateFilters.After,
+ value: moment.unix(startDate).toDate(),
+ }
+ }
+
+ return {}
+}
+
+const DateFilter = ({
+ options,
+ open,
+ setFilter,
+ existingDate,
+ existingFilter,
+}) => {
+ const initialVals = useMemo(() => {
+ const parsed = parseDateFilter(existingDate)
+ return {
+ filterType: options[0],
+ value: null,
+ relativeAmount: undefined,
+ daysMonthsValue: "days",
+ ...parsed,
+ }
+ }, [existingDate])
+
+ const [currentFilter, setCurrentFilter] = useState(initialVals.filterType)
+ const [relativeAmount, setRelativeAmount] = useState(
+ initialVals.relativeAmount
+ )
+ const [daysMonthsValue, setDaysMonthsValue] = useState(
+ initialVals.daysMonthsValue
+ )
+ const [startDate, setStartDate] = useState(initialVals.value)
+
+ useEffect(() => {
+ switch (currentFilter) {
+ case DateFilters.InTheLast:
+ case DateFilters.OlderThan:
+ setFilter({
+ open: true,
+ filter: handleDateFormat(relativeAmount),
+ })
+ break
+ case DateFilters.EqualTo:
+ setFilter({
+ open: true,
+ filter: handleDateFormat(startDate),
+ })
+ break
+ default:
+ setFilter({
+ open: true,
+ filter: handleDateFormat(startDate),
+ })
+ }
+ }, [currentFilter, relativeAmount, daysMonthsValue, startDate])
+
+ const handleDateFormat = (value: string | null) => {
+ switch (currentFilter) {
+ case DateFilters.InTheLast: {
+ // Relative date
+ return { gt: `${value}|${daysMonthsValue}` }
+ }
+
+ case DateFilters.OlderThan: {
+ // Relative date:
+ return { lt: `${value}|${daysMonthsValue}` }
+ }
+
+ case DateFilters.EqualTo: {
+ const momentToSet = atMidnight(value)
+ if (momentToSet) {
+ const day = dateToUnixTimestamp(momentToSet.toDate())
+ const nextDay = dateToUnixTimestamp(
+ addHours(momentToSet, 24).toDate()
+ )
+ return { gt: day, lt: nextDay }
+ } else {
+ return {}
+ }
+ }
+
+ case DateFilters.After: {
+ const momentToSet = atMidnight(value)
+ if (momentToSet) {
+ return { gt: dateToUnixTimestamp(momentToSet.toDate()) }
+ } else {
+ return {}
+ }
+ }
+
+ case DateFilters.Before: {
+ const momentToSet = atMidnight(value)
+ if (momentToSet) {
+ return { lt: dateToUnixTimestamp(momentToSet.toDate()) }
+ } else {
+ return {}
+ }
+ }
+
+ default: {
+ return {}
+ }
+ }
+ }
+
+ const handleFilterContent = () => {
+ switch (currentFilter) {
+ case DateFilters.InTheLast:
+ case DateFilters.OlderThan:
+ return (
+
+
{
+ setRelativeAmount(e.target.value)
+ }}
+ />
+
+
+
+
+
+
+ }
+ >
+
+
+
+ )
+ case DateFilters.EqualTo:
+ case DateFilters.After:
+ case DateFilters.Before:
+ return (
+
+
+
+
+
+
+
+ }
+ >
+ {
+ setStartDate(date)
+ }}
+ />
+
+
+ )
+ }
+ }
+ return (
+
+
+
+
+
+
+
+ }
+ >
+ setCurrentFilter(filter)}
+ selectedItem={currentFilter}
+ />
+
+ {currentFilter && {handleFilterContent()}
}
+
+ )
+}
+
+const PopoverOptions = ({ options, onClick, selectedItem }) => {
+ return (
+ <>
+ {options.map((item) => (
+ {
+ e.stopPropagation()
+ onClick(item)
+ }}
+ className={clsx(
+ "px-3 py-1.5 my-1 flex items-center rounded hover:bg-grey-5 cursor-pointer",
+ {
+ "inter-small-semibold": item === selectedItem,
+ "inter-small-regular": item !== selectedItem,
+ }
+ )}
+ >
+
+ {item === selectedItem && (
+
+ )}
+
+ {item}
+
+ ))}
+ >
+ )
+}
+
+const RightPopover = ({ trigger, children }) => (
+
+
+ {trigger}
+
+
+ {children}
+
+
+)
diff --git a/packages/admin-ui/ui/src/components/molecules/filter-dropdown/save-field.tsx b/packages/admin-ui/ui/src/components/molecules/filter-dropdown/save-field.tsx
new file mode 100644
index 0000000000000..694a82ed8f445
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/filter-dropdown/save-field.tsx
@@ -0,0 +1,45 @@
+import React from "react"
+import Button from "../../fundamentals/button"
+import InputField from "../input"
+import { trim } from "lodash"
+
+type SaveFilterItemProps = {
+ saveFilter: () => void
+ name: string
+ setName: (name: string) => void
+}
+
+const SaveFilterItem: React.FC = ({
+ saveFilter,
+ setName,
+ name,
+}) => {
+ const onSave = () => {
+ const trimmedName = trim(name)
+ if (trimmedName !== "") {
+ saveFilter()
+ setName("")
+ }
+ }
+
+ return (
+
+ setName(e.target.value)}
+ value={name}
+ />
+
+
+ )
+}
+
+export default SaveFilterItem
diff --git a/packages/admin-ui/ui/src/components/molecules/filter-tab/index.tsx b/packages/admin-ui/ui/src/components/molecules/filter-tab/index.tsx
new file mode 100644
index 0000000000000..c808654bfa571
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/filter-tab/index.tsx
@@ -0,0 +1,62 @@
+import React from "react"
+import clsx from "clsx"
+
+import CrossIcon from "../../fundamentals/icons/cross-icon"
+
+type FilterTabProps = {
+ label?: string
+ isActive?: boolean
+ onClick?: React.MouseEventHandler
+ removable?: boolean
+ onRemove?: () => void
+}
+
+export const FilterTab: React.FC = ({
+ label,
+ isActive,
+ onClick,
+ removable,
+ onRemove,
+}) => {
+ const handleClick = (e) => {
+ if (typeof onClick !== "undefined") {
+ onClick(e)
+ }
+ }
+
+ const handleRemove = () => {
+ if (typeof onRemove !== "undefined") {
+ onRemove()
+ }
+ }
+
+ const handleKeyPress = (e) => {
+ if (removable && onRemove) {
+ if (e.key === "Backspace") {
+ onRemove()
+ }
+ }
+ }
+
+ return (
+
+ )
+}
+
+export default FilterTab
diff --git a/packages/admin-ui/ui/src/components/molecules/form-error-toaster/index.tsx b/packages/admin-ui/ui/src/components/molecules/form-error-toaster/index.tsx
new file mode 100644
index 0000000000000..98dcb974de693
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/form-error-toaster/index.tsx
@@ -0,0 +1,41 @@
+import React from "react"
+import { toast as Controller, Toast } from "react-hot-toast"
+import ToasterContainer from "../../atoms/toaster-container"
+import CrossIcon from "../../fundamentals/icons/cross-icon"
+import XCircleIcon from "../../fundamentals/icons/x-circle-icon"
+
+type FormErrorToasterProps = {
+ toast: Toast
+ message: string | React.ReactNode
+ title: string
+}
+
+const FormErrorToaster: React.FC = ({
+ toast,
+ message,
+ title,
+}) => {
+ const onDismiss = () => {
+ Controller.dismiss(toast.id)
+ }
+
+ return (
+
+
+
+
+
+ {title}
+ {message}
+
+
+
+ Close
+
+
+ )
+}
+
+export default FormErrorToaster
diff --git a/packages/admin-ui/ui/src/components/molecules/form-toaster/index.tsx b/packages/admin-ui/ui/src/components/molecules/form-toaster/index.tsx
new file mode 100644
index 0000000000000..ef6c3d8c4a2a8
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/form-toaster/index.tsx
@@ -0,0 +1,177 @@
+import * as Dropdown from "@radix-ui/react-dropdown-menu"
+import clsx from "clsx"
+import React, { Children, HTMLAttributes, useMemo } from "react"
+import { Toast } from "react-hot-toast"
+import Spinner from "../../atoms/spinner"
+import ChevronDownIcon from "../../fundamentals/icons/chevron-down"
+import RefreshIcon from "../../fundamentals/icons/refresh-icon"
+
+type FormToasterContainerProps = {
+ toast?: Toast
+ isLoading?: boolean
+ loadingMessage?: string
+ unsavedChangesMessage?: string
+ icon?: React.ReactNode
+}
+
+type MultiActionButtonProps = {
+ actions: {
+ onClick: () => void | Promise
+ label: string
+ icon?: any
+ }[]
+ className?: string
+}
+
+const FormToasterContainer: React.FC & {
+ Actions: React.FC
+ DiscardButton: React.FC>
+ ActionButton: React.FC>
+ MultiActionButton: React.FC
+} = ({
+ children,
+ toast,
+ isLoading = false,
+ loadingMessage = "Hang on, this may take a few moments...",
+ unsavedChangesMessage = "You have unsaved changes",
+ icon = ,
+}) => {
+ const content = useMemo(() => {
+ if (isLoading) {
+ return (
+
+
+
+
+ {loadingMessage}
+
+ )
+ } else {
+ return (
+ <>
+
+ {icon}
+ {unsavedChangesMessage}
+
+ {children}
+ >
+ )
+ }
+ }, [isLoading, children])
+
+ return (
+
+ )
+}
+
+const Actions: React.FC = ({ children }) => {
+ return (
+
+ {Children.map(children, (child) => {
+ return (
+
+ {child}
+
+ )
+ })}
+
+ )
+}
+
+const DiscardButton: React.FC> = ({
+ children,
+ className,
+ ...props
+}) => {
+ return (
+
+ )
+}
+
+const ActionButton: React.FC> = ({
+ children,
+ className,
+ ...props
+}) => {
+ return (
+
+ )
+}
+
+const MultiActionButton: React.FC = ({
+ children,
+ className,
+ actions,
+}) => {
+ return (
+
+
+ {children}
+
+
+
+
+ {actions.map((action, i) => {
+ return (
+
+
+
+ )
+ })}
+
+
+ )
+}
+
+FormToasterContainer.Actions = Actions
+FormToasterContainer.DiscardButton = DiscardButton
+FormToasterContainer.ActionButton = ActionButton
+FormToasterContainer.MultiActionButton = MultiActionButton
+
+export default FormToasterContainer
diff --git a/packages/admin-ui/ui/src/components/molecules/generating-input/index.tsx b/packages/admin-ui/ui/src/components/molecules/generating-input/index.tsx
new file mode 100644
index 0000000000000..bb731165f7b59
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/generating-input/index.tsx
@@ -0,0 +1,93 @@
+import React, {
+ InputHTMLAttributes,
+ useImperativeHandle,
+ useRef,
+ useState,
+} from "react"
+import { generatePromotionCode } from "../../../utils/generate-promotion-code"
+import RefreshIcon from "../../fundamentals/icons/refresh-icon"
+import InputContainer from "../../fundamentals/input-container"
+import InputHeader from "../../fundamentals/input-header"
+import { InputProps } from "../input"
+
+const GeneratingInput = React.forwardRef(
+ (
+ {
+ placeholder,
+ label,
+ name,
+ required,
+ deletable,
+ onDelete,
+ onChange,
+ onFocus,
+ tooltipContent,
+ tooltip,
+ props,
+ className,
+ value: valueProp,
+ ...fieldProps
+ }: Omit,
+ ref
+ ) => {
+ const [value, setValue] = useState<
+ InputHTMLAttributes["value"]
+ >(valueProp || "")
+ const inputRef = useRef(null)
+
+ useImperativeHandle(ref, () => inputRef.current)
+
+ const generateCode = () => {
+ setValue(generatePromotionCode())
+ }
+
+ const handleChange = (e: React.ChangeEvent) => {
+ setValue(e.target.value)
+ if (onChange) {
+ onChange(e)
+ }
+ }
+
+ return (
+ !fieldProps.disabled && inputRef?.current?.focus()}
+ {...props}
+ >
+
+
+ {!value && (
+
+ )}
+
+
+
+ {value && (
+
+ )}
+
+
+ )
+ }
+)
+
+export default GeneratingInput
diff --git a/packages/admin-ui/ui/src/components/molecules/grid-input/index.tsx b/packages/admin-ui/ui/src/components/molecules/grid-input/index.tsx
new file mode 100644
index 0000000000000..3042034fe7366
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/grid-input/index.tsx
@@ -0,0 +1,15 @@
+import React from "react"
+
+type GridInputProps = React.InputHTMLAttributes
+
+const GridInput: React.FC = ({ value, ...props }) => {
+ return (
+
+ )
+}
+
+export default GridInput
diff --git a/packages/admin-ui/ui/src/components/molecules/hot-key-action/index.tsx b/packages/admin-ui/ui/src/components/molecules/hot-key-action/index.tsx
new file mode 100644
index 0000000000000..ed29a463b4532
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/hot-key-action/index.tsx
@@ -0,0 +1,23 @@
+import React from "react"
+import { useHotkeys } from "react-hotkeys-hook"
+
+type HotKeyActionProps = {
+ label: string
+ hotKey: string
+ icon: React.ReactNode
+ onAction: (keyboardEvent: KeyboardEvent, hotkeysEvent: any) => void | boolean
+}
+
+const HotKeyAction = ({ label, hotKey, icon, onAction }: HotKeyActionProps) => {
+ useHotkeys(hotKey, onAction, {})
+ return (
+
+ )
+}
+
+export default HotKeyAction
diff --git a/packages/admin-ui/ui/src/components/molecules/icon-tooltip/index.tsx b/packages/admin-ui/ui/src/components/molecules/icon-tooltip/index.tsx
new file mode 100644
index 0000000000000..dfccbb24b71e2
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/icon-tooltip/index.tsx
@@ -0,0 +1,36 @@
+import React from "react"
+import Tooltip, { TooltipProps } from "../../atoms/tooltip"
+import AlertIcon from "../../fundamentals/icons/alert-icon"
+import InfoIcon from "../../fundamentals/icons/info-icon"
+import IconProps from "../../fundamentals/icons/types/icon-type"
+import XCircleIcon from "../../fundamentals/icons/x-circle-icon"
+
+type IconTooltipProps = TooltipProps & {
+ type?: "info" | "warning" | "error"
+} & Pick
+
+const IconTooltip: React.FC = ({
+ type = "info",
+ size = 16,
+ content,
+ ...props
+}) => {
+ const icon = (type: IconTooltipProps["type"]) => {
+ switch (type) {
+ case "warning":
+ return
+ case "error":
+ return
+ default:
+ return
+ }
+ }
+
+ return (
+
+ {icon(type)}
+
+ )
+}
+
+export default IconTooltip
diff --git a/packages/admin-ui/ui/src/components/molecules/indeterminate-checkbox/index.tsx b/packages/admin-ui/ui/src/components/molecules/indeterminate-checkbox/index.tsx
new file mode 100644
index 0000000000000..5fef801d78f30
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/indeterminate-checkbox/index.tsx
@@ -0,0 +1,82 @@
+import clsx from "clsx"
+import React, { useImperativeHandle } from "react"
+
+import CheckIcon from "../../fundamentals/icons/check-icon"
+
+type IndeterminateCheckboxProps = {
+ type?: "checkbox" | "radio"
+ onChange?: (e: React.ChangeEvent) => void
+ checked?: boolean
+ title?: string
+ indeterminate?: boolean
+ className?: React.HTMLAttributes["className"]
+ name?: string
+ disabled?: boolean // NOTE: only visual, still have to filter disabled ids out
+}
+
+const IndeterminateCheckbox = React.forwardRef<
+ HTMLInputElement,
+ IndeterminateCheckboxProps
+>(({ indeterminate = false, className, checked, ...rest }, ref) => {
+ const type = rest.type || "checkbox"
+ const innerRef = React.useRef(null)
+
+ useImperativeHandle(
+ ref,
+ () => innerRef.current
+ )
+
+ React.useEffect(() => {
+ if (innerRef.current) {
+ innerRef.current.indeterminate = indeterminate
+ }
+ }, [innerRef, indeterminate])
+
+ const handleClick = () => {
+ if (!rest.disabled && innerRef.current) {
+ innerRef.current.click()
+ }
+ }
+
+ if (type === "radio") {
+ return (
+
+
+
+ )
+ }
+
+ return (
+
+
+
+ {checked && }
+
+
+
+
+ )
+})
+
+export default IndeterminateCheckbox
diff --git a/packages/admin-ui/ui/src/components/molecules/input-signin/index.tsx b/packages/admin-ui/ui/src/components/molecules/input-signin/index.tsx
new file mode 100644
index 0000000000000..df64198fdef8b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/input-signin/index.tsx
@@ -0,0 +1,99 @@
+import clsx from "clsx"
+import React, {
+ ChangeEventHandler,
+ FocusEventHandler,
+ useEffect,
+ useImperativeHandle,
+ useRef,
+ useState,
+} from "react"
+import EyeIcon from "../../fundamentals/icons/eye-icon"
+import EyeOffIcon from "../../fundamentals/icons/eye-off-icon"
+import LockIcon from "../../fundamentals/icons/lock-icon"
+
+type InputProps = React.InputHTMLAttributes & {
+ key?: string
+ onChange?: ChangeEventHandler
+ onFocus?: FocusEventHandler
+ props?: React.HTMLAttributes
+}
+
+const SigninInput = React.forwardRef(
+ (
+ {
+ placeholder,
+ name,
+ key,
+ required,
+ onChange,
+ onFocus,
+ className,
+ type,
+ ...props
+ }: InputProps,
+ ref
+ ) => {
+ const inputRef = useRef(null)
+ const [showPassword, setShowPassword] = useState(false)
+ const [inputType, setInputType] = useState(type)
+
+ useEffect(() => {
+ if (type === "password" && showPassword) {
+ setInputType("text")
+ }
+
+ if (type === "password" && !showPassword) {
+ setInputType("password")
+ }
+ }, [type, showPassword])
+
+ useImperativeHandle(ref, () => inputRef.current)
+
+ return (
+
+ {props.readOnly && (
+
+ )}
+
+ {type === "password" && (
+
+ )}
+
+ )
+ }
+)
+
+export default SigninInput
diff --git a/packages/admin-ui/ui/src/components/molecules/input/index.tsx b/packages/admin-ui/ui/src/components/molecules/input/index.tsx
new file mode 100644
index 0000000000000..396dd17fb8513
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/input/index.tsx
@@ -0,0 +1,155 @@
+import clsx from "clsx"
+import React, {
+ ChangeEventHandler,
+ FocusEventHandler,
+ MouseEventHandler,
+ useImperativeHandle,
+ useRef,
+} from "react"
+import InputError from "../../atoms/input-error"
+import MinusIcon from "../../fundamentals/icons/minus-icon"
+import PlusIcon from "../../fundamentals/icons/plus-icon"
+import InputHeader, { InputHeaderProps } from "../../fundamentals/input-header"
+
+export type InputProps = Omit, "prefix"> &
+ InputHeaderProps & {
+ small?: boolean
+ label?: string
+ deletable?: boolean
+ onDelete?: MouseEventHandler
+ onChange?: ChangeEventHandler
+ onFocus?: FocusEventHandler
+ errors?: { [x: string]: unknown }
+ prefix?: React.ReactNode
+ props?: React.HTMLAttributes
+ }
+
+const InputField = React.forwardRef(
+ (
+ {
+ small,
+ placeholder,
+ label,
+ name,
+ required,
+ deletable,
+ onDelete,
+ onChange,
+ onFocus,
+ tooltipContent,
+ tooltip,
+ prefix,
+ errors,
+ props,
+ className,
+ ...fieldProps
+ }: InputProps,
+ ref
+ ) => {
+ const inputRef = useRef(null)
+
+ useImperativeHandle(
+ ref,
+ () => inputRef.current
+ )
+
+ const onNumberIncrement = () => {
+ inputRef.current?.stepUp()
+ if (onChange) {
+ inputRef.current?.dispatchEvent(
+ new InputEvent("change", {
+ view: window,
+ bubbles: true,
+ cancelable: false,
+ })
+ )
+ }
+ }
+
+ const onNumberDecrement = () => {
+ inputRef.current?.stepDown()
+ if (onChange) {
+ inputRef.current?.dispatchEvent(
+ new InputEvent("change", {
+ view: window,
+ bubbles: true,
+ cancelable: false,
+ })
+ )
+ }
+ }
+
+ return (
+
+ {label && (
+
+ )}
+
+ {prefix ? (
+
{prefix}
+ ) : null}
+
+
+ {deletable && (
+
+ )}
+
+ {fieldProps.type === "number" && (
+
+
+
+
+ )}
+
+
+
+ )
+ }
+)
+
+export default InputField
diff --git a/packages/admin-ui/ui/src/components/molecules/json-view/index.tsx b/packages/admin-ui/ui/src/components/molecules/json-view/index.tsx
new file mode 100644
index 0000000000000..37a7db3a06975
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/json-view/index.tsx
@@ -0,0 +1,94 @@
+import * as Collapsible from "@radix-ui/react-collapsible"
+import clsx from "clsx"
+import { useMemo, useState } from "react"
+import { JSONTree } from "react-json-tree"
+import useClipboard from "../../../hooks/use-clipboard"
+import Button from "../../fundamentals/button"
+import ChevronDownIcon from "../../fundamentals/icons/chevron-down"
+import ClipboardCopyIcon from "../../fundamentals/icons/clipboard-copy-icon"
+
+type JSONViewProps = {
+ data: object
+}
+
+const JSONView = ({ data }: JSONViewProps) => {
+ const [expanded, setExpanded] = useState(false)
+ const [isCopied, handleCopy] = useClipboard(
+ JSON.stringify(data, undefined, 2),
+ {
+ successDuration: 5500,
+ onCopied: () => {},
+ }
+ )
+
+ const length = useMemo(() => {
+ return Object.keys(data).length
+ }, [data])
+
+ return (
+
+
+
+
+
+
+ {expanded ? "{" : length > 0 ? "{ ... }" : "{}"}
+
+
+ ({length} {length === 1 ? "item" : "items"})
+
+
+
+
+
+
+
+ false}
+ />
+
+
+ {expanded &&
{`}`}
}
+
+ {isCopied && (
+ Copied!
+ )}
+
+
+
+
+
+
+ )
+}
+
+export default JSONView
diff --git a/packages/admin-ui/ui/src/components/molecules/modal/focus-modal.tsx b/packages/admin-ui/ui/src/components/molecules/modal/focus-modal.tsx
new file mode 100644
index 0000000000000..bc8c02b07f42f
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/modal/focus-modal.tsx
@@ -0,0 +1,114 @@
+import clsx from "clsx"
+
+import Button from "../../fundamentals/button"
+import CrossIcon from "../../fundamentals/icons/cross-icon"
+import { ReactFCWithChildren } from "../../../types/utils"
+
+type FocusModalElementProps = {
+ className?: string
+ children?: React.ReactNode
+}
+
+type IFocusModal = ReactFCWithChildren & {
+ Header: ReactFCWithChildren
+ Main: ReactFCWithChildren
+ BasicFocusModal: ReactFCWithChildren
+}
+
+type BasicFocusModalProps = {
+ handleClose: (e) => void
+ onSubmit: (e) => void
+ cancelText?: string
+ submitText?: string
+ children?: React.ReactNode
+}
+
+const FocusModal: IFocusModal = ({ className, children }) => (
+
+ {children}
+
+)
+
+FocusModal.Header = ({ children, className }) => (
+
+ {children}
+
+)
+
+FocusModal.Main = ({ children, className }) => (
+
+ {children}
+
+)
+
+FocusModal.BasicFocusModal = ({
+ handleClose,
+ onSubmit,
+ children,
+ cancelText = "Cancel",
+ submitText = "Save changes",
+}) => {
+ return (
+
+
+ {children}
+
+ )
+}
+
+const BasicFocusModalHeader: React.FC = ({
+ handleClose,
+ onSubmit,
+ cancelText,
+ submitText,
+}) => {
+ return (
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default FocusModal
diff --git a/packages/admin-ui/ui/src/components/molecules/modal/index.tsx b/packages/admin-ui/ui/src/components/molecules/modal/index.tsx
new file mode 100644
index 0000000000000..43a741ff0aab1
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/modal/index.tsx
@@ -0,0 +1,161 @@
+import * as Dialog from "@radix-ui/react-dialog"
+import * as Portal from "@radix-ui/react-portal"
+import clsx from "clsx"
+import React from "react"
+import { useWindowDimensions } from "../../../hooks/use-window-dimensions"
+import CrossIcon from "../../fundamentals/icons/cross-icon"
+
+type ModalState = {
+ portalRef: any
+ isLargeModal?: boolean
+}
+
+export const ModalContext = React.createContext({
+ portalRef: undefined,
+ isLargeModal: true,
+})
+
+export type ModalProps = {
+ isLargeModal?: boolean
+ handleClose: () => void
+ open?: boolean
+ children?: React.ReactNode
+}
+
+type ModalChildProps = {
+ className?: string
+ style?: React.CSSProperties
+ children?: React.ReactNode
+}
+
+type ModalHeaderProps = {
+ handleClose: () => void
+ children?: React.ReactNode
+}
+
+type ModalType = React.FC & {
+ Body: React.FC
+ Header: React.FC
+ Footer: React.FC
+ Content: React.FC
+}
+
+const Overlay: React.FC = ({ children }) => {
+ return (
+
+ {children}
+
+ )
+}
+
+const Content: React.FC = ({ children }) => {
+ const { height } = useWindowDimensions()
+ const style = {
+ maxHeight: height - 64,
+ }
+ return (
+
+ {children}
+
+ )
+}
+
+const Modal: ModalType = ({
+ open = true,
+ handleClose,
+ isLargeModal = true,
+ children,
+}) => {
+ const portalRef = React.useRef(null)
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ )
+}
+
+Modal.Body = ({ children, className, style }) => {
+ const { isLargeModal } = React.useContext(ModalContext)
+
+ return (
+ e.stopPropagation()}
+ >
+ {children}
+
+ )
+}
+
+Modal.Content = ({ children, className }) => {
+ const { isLargeModal } = React.useContext(ModalContext)
+
+ const { height } = useWindowDimensions()
+ const style = {
+ maxHeight: height - 90 - 141,
+ }
+ return (
+
+ {children}
+
+ )
+}
+
+Modal.Header = ({ handleClose = undefined, children }) => {
+ return (
+ e.stopPropagation()}
+ >
+
+ {handleClose && (
+
+ )}
+
+ {children}
+
+ )
+}
+
+Modal.Footer = ({ children, className }) => {
+ const { isLargeModal } = React.useContext(ModalContext)
+
+ return (
+ e.stopPropagation()}
+ className={clsx(
+ "px-7 bottom-0 pb-5 flex w-full",
+ {
+ "border-t border-grey-20 pt-4": isLargeModal,
+ },
+ className
+ )}
+ >
+ {children}
+
+ )
+}
+
+export default Modal
diff --git a/packages/admin-ui/ui/src/components/molecules/modal/layered-modal.tsx b/packages/admin-ui/ui/src/components/molecules/modal/layered-modal.tsx
new file mode 100644
index 0000000000000..bdb84c0ce921b
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/modal/layered-modal.tsx
@@ -0,0 +1,163 @@
+import clsx from "clsx"
+import React, { ReactNode, useContext, useReducer } from "react"
+import Button from "../../fundamentals/button"
+import ArrowLeftIcon from "../../fundamentals/icons/arrow-left-icon"
+import Modal, { ModalProps } from "../../molecules/modal"
+
+enum LayeredModalActions {
+ PUSH,
+ POP,
+ RESET,
+}
+
+export type LayeredModalScreen = {
+ title: string
+ subtitle?: string
+ onBack: () => void
+ onConfirm?: () => void
+ view: ReactNode
+}
+
+export type ILayeredModalContext = {
+ screens: LayeredModalScreen[]
+ push: (screen: LayeredModalScreen) => void
+ pop: () => void
+ reset: () => void
+}
+
+const defaultContext: ILayeredModalContext = {
+ screens: [],
+ push: (screen) => {},
+ pop: () => {},
+ reset: () => {},
+}
+
+export const LayeredModalContext = React.createContext(defaultContext)
+
+const reducer = (state, action) => {
+ switch (action.type) {
+ case LayeredModalActions.PUSH: {
+ return { ...state, screens: [...state.screens, action.payload] }
+ }
+ case LayeredModalActions.POP: {
+ return { ...state, screens: state.screens.slice(0, -1) }
+ }
+ case LayeredModalActions.RESET: {
+ return { ...state, screens: [] }
+ }
+ }
+}
+
+type LayeredModalProps = {
+ context: ILayeredModalContext
+} & ModalProps
+
+export const LayeredModalProvider = ({ children }) => {
+ const [state, dispatch] = useReducer(reducer, defaultContext)
+
+ return (
+ {
+ dispatch({ type: LayeredModalActions.PUSH, payload: screen })
+ },
+
+ pop: () => {
+ dispatch({ type: LayeredModalActions.POP })
+ },
+
+ reset: () => {
+ dispatch({ type: LayeredModalActions.RESET })
+ },
+ }}
+ >
+ {children}
+
+ )
+}
+
+const LayeredModal: React.FC = ({
+ context,
+ children,
+ handleClose,
+ open,
+ isLargeModal = true,
+}) => {
+ const emptyScreensAndClose = () => {
+ context.reset()
+ handleClose()
+ }
+
+ const screen = context.screens[context.screens.length - 1]
+ return (
+
+
+ {screen ? (
+ <>
+
+
+
+
+
{screen.title}
+ {screen.subtitle && (
+
+ ({screen.subtitle})
+
+ )}
+
+
+
+ {screen.view}
+ >
+ ) : (
+ <>>
+ )}
+
+
+
+ )
+}
+
+export const useLayeredModal = () => {
+ const context = useContext(LayeredModalContext)
+ if (context === null) {
+ throw new Error(
+ "useLayeredModal must be used within a LayeredModalProvider"
+ )
+ }
+ return context
+}
+
+export default LayeredModal
diff --git a/packages/admin-ui/ui/src/components/molecules/modal/side-modal.tsx b/packages/admin-ui/ui/src/components/molecules/modal/side-modal.tsx
new file mode 100644
index 0000000000000..14f49334034cf
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/modal/side-modal.tsx
@@ -0,0 +1,60 @@
+import React, { PropsWithChildren } from "react"
+import { AnimatePresence, motion } from "framer-motion"
+
+const MODAL_WIDTH = 560
+
+type SideModalProps = PropsWithChildren<{
+ close: () => void
+ isVisible: boolean
+}>
+
+/**
+ * Side modal displayed as right drawer on open.
+ */
+function SideModal(props: SideModalProps) {
+ const { isVisible, children, close } = props
+ return (
+
+ {isVisible && (
+ <>
+
+
+ {children}
+
+ >
+ )}
+
+ )
+}
+
+export default SideModal
diff --git a/packages/admin-ui/ui/src/components/molecules/modal/stepped-modal.tsx b/packages/admin-ui/ui/src/components/molecules/modal/stepped-modal.tsx
new file mode 100644
index 0000000000000..6c5bfef9f7f0d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/modal/stepped-modal.tsx
@@ -0,0 +1,227 @@
+import clsx from "clsx"
+import React, { ReactNode, useReducer } from "react"
+import Button from "../../fundamentals/button"
+import Modal, { ModalProps } from "../../molecules/modal"
+import LayeredModal, { ILayeredModalContext } from "./layered-modal"
+
+enum SteppedActions {
+ ENABLENEXTPAGE,
+ DISABLENEXTPAGE,
+ GOTONEXTPAGE,
+ GOTOPREVIOUSPAGE,
+ SETPAGE,
+ SUBMIT,
+ RESET,
+}
+
+type ISteppedContext = {
+ currentStep: number
+ nextStepEnabled: boolean
+ enableNextPage: () => void
+ disableNextPage: () => void
+ goToNextPage: () => void
+ goToPreviousPage: () => void
+ submit: () => void
+ reset: () => void
+ setPage: (page: number) => void
+}
+
+const defaultContext: ISteppedContext = {
+ currentStep: 0,
+ nextStepEnabled: true,
+ enableNextPage: () => {},
+ disableNextPage: () => {},
+ goToNextPage: () => {},
+ goToPreviousPage: () => {},
+ submit: () => {},
+ reset: () => {},
+ setPage: (page) => {},
+}
+
+export const SteppedContext = React.createContext(defaultContext)
+
+const reducer = (state, action) => {
+ switch (action.type) {
+ case SteppedActions.ENABLENEXTPAGE: {
+ return { ...state, nextStepEnabled: true }
+ }
+ case SteppedActions.DISABLENEXTPAGE: {
+ return { ...state, nextStepEnabled: false }
+ }
+ case SteppedActions.GOTONEXTPAGE: {
+ return { ...state, currentStep: state.currentStep + 1 }
+ }
+ case SteppedActions.GOTOPREVIOUSPAGE: {
+ return { ...state, currentStep: Math.max(0, state.currentStep - 1) }
+ }
+ case SteppedActions.SETPAGE: {
+ return {
+ ...state,
+ currentStep: action.payload > 0 ? action.payload : state.currentStep,
+ }
+ }
+ case SteppedActions.SUBMIT: {
+ return { ...state }
+ }
+ case SteppedActions.RESET: {
+ return { ...state, currentStep: 0, nextStepEnabled: true }
+ }
+ }
+}
+
+type SteppedProps = {
+ context: ISteppedContext
+ title: string
+ onSubmit: () => void
+ lastScreenIsSummary?: boolean
+ steps: ReactNode[]
+ layeredContext?: ILayeredModalContext
+} & ModalProps
+
+export const SteppedProvider = ({ children }) => {
+ const [state, dispatch] = useReducer(reducer, defaultContext)
+
+ return (
+ {
+ dispatch({ type: SteppedActions.ENABLENEXTPAGE })
+ },
+ disableNextPage: () => {
+ dispatch({ type: SteppedActions.DISABLENEXTPAGE })
+ },
+ goToNextPage: () => {
+ dispatch({ type: SteppedActions.GOTONEXTPAGE })
+ },
+ goToPreviousPage: () => {
+ dispatch({ type: SteppedActions.GOTOPREVIOUSPAGE })
+ },
+ submit: () => {
+ dispatch({ type: SteppedActions.SUBMIT })
+ },
+ setPage: (page: number) => {
+ dispatch({ type: SteppedActions.SETPAGE, payload: page })
+ },
+ reset: () => {
+ dispatch({ type: SteppedActions.RESET })
+ },
+ }}
+ >
+ {children}
+
+ )
+}
+
+const SteppedModal: React.FC = ({
+ context,
+ steps,
+ layeredContext,
+ title,
+ onSubmit,
+ lastScreenIsSummary = false,
+ handleClose,
+ isLargeModal = true,
+}) => {
+ const resetAndClose = () => {
+ context.reset()
+ handleClose()
+ }
+
+ const resetAndSubmit = () => {
+ onSubmit()
+ }
+ return (
+
+
+
+
+
{title}
+ {!lastScreenIsSummary ||
+ (lastScreenIsSummary &&
+ context.currentStep !== steps.length - 1 && (
+
+ {`Step ${
+ context.currentStep + 1
+ } of ${steps.length}`}
+ {steps.map((_, i) => (
+ context.currentStep,
+ "bg-violet-60": context.currentStep >= i,
+ },
+ {
+ "outline-4 outline outline-violet-20":
+ context.currentStep === i,
+ }
+ )}
+ />
+ ))}
+
+ ))}
+
+
+ {steps[context.currentStep]}
+
+
+
+
+
+
+
+
+ )
+}
+
+const ModalElement = ({
+ layeredContext,
+ handleClose,
+ isLargeModal = true,
+ children,
+}) =>
+ layeredContext ? (
+
+ {children}
+
+ ) : (
+
+ {children}
+
+ )
+
+export default SteppedModal
diff --git a/packages/admin-ui/ui/src/components/molecules/native-select/index.tsx b/packages/admin-ui/ui/src/components/molecules/native-select/index.tsx
new file mode 100644
index 0000000000000..d44ad179e6499
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/native-select/index.tsx
@@ -0,0 +1,68 @@
+import * as RadixSelect from "@radix-ui/react-select"
+import clsx from "clsx"
+import React from "react"
+import CheckIcon from "../../fundamentals/icons/check-icon"
+import ChevronDownIcon from "../../fundamentals/icons/chevron-down"
+import ChevronUpIcon from "../../fundamentals/icons/chevron-up"
+
+type NativeSelectType = React.FC & {
+ Item: React.FC
+}
+
+type NativeSelectProps = {
+ triggerProps?: RadixSelect.SelectTriggerProps
+} & RadixSelect.SelectProps
+
+const ICON_SIZE = 16
+
+const NativeSelect: NativeSelectType = ({
+ children,
+ triggerProps,
+ ...props
+}) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+ )
+}
+
+type ItemProps = RadixSelect.SelectItemProps
+
+const Item: React.FC = ({ children, ...props }) => (
+
+
+
+
+ {children}
+
+)
+
+NativeSelect.Item = Item
+
+export default NativeSelect
diff --git a/packages/admin-ui/ui/src/components/molecules/note-input/index.tsx b/packages/admin-ui/ui/src/components/molecules/note-input/index.tsx
new file mode 100644
index 0000000000000..ad88395dfc18d
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/note-input/index.tsx
@@ -0,0 +1,76 @@
+import React, { useCallback, useRef, useState } from "react"
+import SendIcon from "../../fundamentals/icons/send-icon"
+import EmojiPicker from "../emoji-picker"
+
+type NoteInputProps = {
+ onSubmit: (note: string | undefined) => void
+}
+
+const NoteInput: React.FC = ({ onSubmit }) => {
+ const [note, setNote] = useState(undefined)
+ const inputRef = useRef(null)
+
+ const handleAddEmoji = (emoji: string) => {
+ setNote(`${note ? note : ""}${emoji}`)
+ }
+
+ const handleSubmit = () => {
+ if (onSubmit && note) {
+ onSubmit(note)
+ setNote("")
+ }
+ }
+
+ const onKeyDownHandler = useCallback(
+ (event) => {
+ switch (event.key) {
+ case "Enter":
+ event.preventDefault()
+ event.stopPropagation()
+ handleSubmit()
+ inputRef.current?.blur()
+ break
+ case "Esc":
+ case "Escape":
+ inputRef.current?.blur()
+ break
+ default:
+ break
+ }
+ },
+ [note, setNote, onSubmit]
+ )
+
+ return (
+
+ )
+}
+
+export default NoteInput
diff --git a/packages/admin-ui/ui/src/components/molecules/notification-bell/index.tsx b/packages/admin-ui/ui/src/components/molecules/notification-bell/index.tsx
new file mode 100644
index 0000000000000..e466da7880945
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/notification-bell/index.tsx
@@ -0,0 +1,21 @@
+import React from "react"
+import Button, { ButtonProps } from "../../fundamentals/button"
+import BellIcon from "../../fundamentals/icons/bell-icon"
+import BellNotiIcon from "../../fundamentals/icons/bell-noti-icon"
+
+type NotificationBellProps = ButtonProps & {
+ hasNotifications?: boolean
+}
+
+const NotificationBell: React.FC = ({
+ hasNotifications = false,
+ ...attributes
+}) => {
+ return (
+
+ )
+}
+
+export default NotificationBell
diff --git a/packages/admin-ui/ui/src/components/molecules/numbered-item/index.tsx b/packages/admin-ui/ui/src/components/molecules/numbered-item/index.tsx
new file mode 100644
index 0000000000000..c04f2b8f5aba4
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/numbered-item/index.tsx
@@ -0,0 +1,52 @@
+import React from "react"
+import Badge from "../../../components/fundamentals/badge"
+import Actionables, {
+ ActionType,
+} from "../../../components/molecules/actionables"
+
+type NumberedItemProps = {
+ actions?: ActionType[]
+ index: number
+ title: string
+ description?: React.ReactNode | string
+}
+
+const NumberedItem: React.FC = ({
+ actions,
+ index,
+ title,
+ description,
+}) => {
+ return (
+
+
+
+
+ §{index}
+
+
+
+
{title}
+ {description &&
+ (typeof description === "string" ? (
+
+ {description}
+
+ ) : (
+ description
+ ))}
+
+
+ {actions && (
+
+ )}
+
+ )
+}
+
+export default NumberedItem
diff --git a/packages/admin-ui/ui/src/components/molecules/order-status/index.tsx b/packages/admin-ui/ui/src/components/molecules/order-status/index.tsx
new file mode 100644
index 0000000000000..9a8c0838d723a
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/order-status/index.tsx
@@ -0,0 +1,113 @@
+import React from "react"
+import StatusIndicator from "../../fundamentals/status-indicator"
+
+type PaymentStatusProps = {
+ paymentStatus: string
+}
+
+type FulfillmentStatusProps = {
+ fulfillmentStatus: string
+}
+
+type OrderStatusProps = {
+ orderStatus: string
+}
+
+type ReturnStatusProps = {
+ returnStatus: string
+}
+
+type RefundStatusProps = {
+ refundStatus: string
+}
+
+const PaymentStatus: React.FC = ({ paymentStatus }) => {
+ switch (paymentStatus) {
+ case "captured":
+ return
+ case "awaiting":
+ return
+ case "not_paid":
+ return
+ case "canceled":
+ return
+ case "requires_action":
+ return
+ default:
+ return null
+ }
+}
+
+const OrderStatus: React.FC = ({ orderStatus }) => {
+ switch (orderStatus) {
+ case "completed":
+ return
+ case "pending":
+ return
+ case "canceled":
+ return
+ case "requires_action":
+ return
+ default:
+ return null
+ }
+}
+
+const FulfillmentStatus: React.FC = ({
+ fulfillmentStatus,
+}) => {
+ switch (fulfillmentStatus) {
+ case "shipped":
+ return
+ case "fulfilled":
+ return
+ case "canceled":
+ return
+ case "partially_fulfilled":
+ return
+ case "not_fulfilled":
+ return
+ case "requires_action":
+ return
+ default:
+ return null
+ }
+}
+
+const ReturnStatus: React.FC = ({ returnStatus }) => {
+ switch (returnStatus) {
+ case "received":
+ return
+ case "requested":
+ return
+ case "canceled":
+ return
+ case "requires_action":
+ return
+ default:
+ return null
+ }
+}
+
+const RefundStatus: React.FC = ({ refundStatus }) => {
+ switch (refundStatus) {
+ case "na":
+ return
+ case "not_refunded":
+ return
+ case "refunded":
+ return
+ case "canceled":
+ return
+ default:
+ return null
+ }
+}
+
+export {
+ PaymentStatus,
+ OrderStatus,
+ FulfillmentStatus,
+ ReturnStatus,
+ RefundStatus,
+}
diff --git a/packages/admin-ui/ui/src/components/molecules/rma-select-shipping/index.tsx b/packages/admin-ui/ui/src/components/molecules/rma-select-shipping/index.tsx
new file mode 100644
index 0000000000000..5f5912eed9fcb
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/rma-select-shipping/index.tsx
@@ -0,0 +1,54 @@
+import React from "react"
+import Button from "../../fundamentals/button"
+import TrashIcon from "../../fundamentals/icons/trash-icon"
+import { AmountInput } from "../amount-input"
+
+type RMAShippingPriceProps = {
+ inclTax: boolean
+ useCustomShippingPrice: boolean
+ shippingPrice: number | undefined
+ currencyCode: string
+ updateShippingPrice: (price: number | undefined) => void
+ setUseCustomShippingPrice: (useCustomShippingPrice: boolean) => void
+}
+
+const RMAShippingPrice: React.FC = ({
+ useCustomShippingPrice,
+ inclTax,
+ shippingPrice,
+ currencyCode,
+ updateShippingPrice,
+ setUseCustomShippingPrice,
+}) => {
+ return useCustomShippingPrice ? (
+
+
updateShippingPrice(amount ?? 0)}
+ value={shippingPrice}
+ />
+
+
+ ) : (
+
+
+
+ )
+}
+
+export default RMAShippingPrice
diff --git a/packages/admin-ui/ui/src/components/molecules/sales-channels-display/index.tsx b/packages/admin-ui/ui/src/components/molecules/sales-channels-display/index.tsx
new file mode 100644
index 0000000000000..7aa4d6d88c1fe
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/sales-channels-display/index.tsx
@@ -0,0 +1,70 @@
+import { SalesChannel } from "@medusajs/medusa"
+import { useAdminSalesChannels } from "medusa-react"
+import React from "react"
+import Tooltip from "../../atoms/tooltip"
+import Badge from "../../fundamentals/badge"
+
+type Props = {
+ channels?: SalesChannel[]
+}
+
+const SalesChannelsDisplay = ({ channels = [] }: Props) => {
+ const { count } = useAdminSalesChannels()
+ const remainder = Math.max(channels.length - 3, 0)
+
+ return (
+
+ {channels.length > 0 && (
+
+
+ {channels.slice(0, 3).map((sc) => (
+
+ ))}
+
+ {remainder > 0 && (
+
+ {channels.slice(3).map((sc) => {
+ return {sc.name}
+ })}
+
+ }
+ >
+
+
+ + {remainder} more
+
+
+
+ )}
+
+ )}
+
+ Available in{" "}
+
+ {channels.length ? channels.length : 0}
+ {" "}
+ out of{" "}
+ {count || 0}{" "}
+ Sales Channels
+
+
+ )
+}
+
+type SalesChannelBadgeProps = {
+ channel: SalesChannel
+}
+
+const SalesChannelBadge: React.FC = ({ channel }) => {
+ return (
+
+
+ {channel.name}
+
+
+ )
+}
+
+export default SalesChannelsDisplay
diff --git a/packages/admin-ui/ui/src/components/molecules/sales-channels-list/index.tsx b/packages/admin-ui/ui/src/components/molecules/sales-channels-list/index.tsx
new file mode 100644
index 0000000000000..b576c0eba0f21
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/sales-channels-list/index.tsx
@@ -0,0 +1,46 @@
+import { SalesChannel } from "@medusajs/medusa"
+import Tooltip from "../../atoms/tooltip"
+import IconBadge from "../../fundamentals/icon-badge"
+import ChannelsIcon from "../../fundamentals/icons/channels-icon"
+
+type Props = {
+ salesChannels: SalesChannel[]
+ showMax?: number
+}
+
+const SalesChannelsList = ({ salesChannels, showMax = 3 }: Props) => {
+ const truncateSalesChannels = salesChannels.length > showMax
+ return (
+
+
+
+
+ {salesChannels
+ .slice(0, showMax)
+ .map((salesChannel, index, slicedArray) => (
+
+ {salesChannel.name}
+ {index < slicedArray.length - 1 && ", "}
+
+ ))}
+ {truncateSalesChannels && (
+
+ {salesChannels.slice(showMax).map((channel) => (
+ {channel.name}
+ ))}
+ >
+ }
+ side="top"
+ >
+
+ + {salesChannels.length - showMax} more
+
+
+ )}
+
+ )
+}
+
+export default SalesChannelsList
diff --git a/packages/admin-ui/ui/src/components/molecules/sales-channels-summary/index.tsx b/packages/admin-ui/ui/src/components/molecules/sales-channels-summary/index.tsx
new file mode 100644
index 0000000000000..b8110ef5c47b8
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/sales-channels-summary/index.tsx
@@ -0,0 +1,39 @@
+import { sortBy } from "lodash"
+
+import { SalesChannel } from "@medusajs/medusa"
+
+/**
+ * Customers Associated Groups props
+ */
+interface P {
+ channels: SalesChannel[]
+ showCount: number
+}
+
+/*
+ * Render a summary of groups to which the customer belongs
+ */
+function SalesChannelsSummary(props: P) {
+ const channels = sortBy(props.channels, "name")
+ if (!channels.length) {
+ return null
+ }
+
+ const allGroups = channels.map((g) => g.name).join(", ")
+
+ const leadName = channels
+ .slice(0, props.showCount)
+ .map((g) => g.name)
+ .join(", ")
+
+ const left = channels.length - props.showCount
+
+ return (
+
+ {leadName}
+ {left > 0 && + {left} more}
+
+ )
+}
+
+export default SalesChannelsSummary
diff --git a/packages/admin-ui/ui/src/components/molecules/search-bar.tsx b/packages/admin-ui/ui/src/components/molecules/search-bar.tsx
new file mode 100644
index 0000000000000..6d2ddb86adfd4
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/search-bar.tsx
@@ -0,0 +1,49 @@
+import React, { useEffect, useState } from "react"
+import { useHotkeys } from "react-hotkeys-hook"
+import { useLocation } from "react-router-dom"
+import OSShortcut from "../atoms/os-shortcut"
+import SearchIcon from "../fundamentals/icons/search-icon"
+import SearchModal from "../templates/search-modal"
+
+const SearchBar: React.FC = () => {
+ const [showSearchModal, setShowSearchModal] = useState(false)
+ const location = useLocation()
+
+ const toggleSearch = (e) => {
+ e.preventDefault()
+ e.stopPropagation()
+ setShowSearchModal((show) => !show)
+ }
+
+ const closeModal = () => {
+ setShowSearchModal(false)
+ }
+
+ useHotkeys("cmd+k", toggleSearch, {}, [])
+ useHotkeys("ctrl+k", toggleSearch, {}, [])
+ useHotkeys("/", toggleSearch, {}, [])
+
+ useEffect(() => {
+ closeModal()
+ }, [location])
+
+ return (
+ <>
+
+ {showSearchModal && }
+ >
+ )
+}
+
+export default SearchBar
diff --git a/packages/admin-ui/ui/src/components/molecules/section/index.tsx b/packages/admin-ui/ui/src/components/molecules/section/index.tsx
new file mode 100644
index 0000000000000..1cc1796b794b5
--- /dev/null
+++ b/packages/admin-ui/ui/src/components/molecules/section/index.tsx
@@ -0,0 +1,32 @@
+import React from "react"
+import IconTooltip from "../icon-tooltip"
+
+type SectionProps = {
+ title: string
+ description: string
+ tooltip?: string
+}
+
+const Section: React.FC = ({
+ title,
+ description,
+ tooltip,
+ children,
+}) => {
+ return (
+
+