├── .github └── workflows │ └── cd.yml ├── .gitignore ├── README.md ├── biome.json ├── graphql.config.yml ├── index.html ├── package.json ├── pnpm-lock.yaml ├── postcss.config.cjs ├── public └── vite.svg ├── schema-storefront.graphql ├── src ├── App.tsx ├── assets │ └── usage-stately-actors.mp4 ├── commons │ ├── entities.ts │ └── http-errors.ts ├── components │ └── Notifications.tsx ├── data │ └── library-static-images-resources.data.ts ├── environment.ts ├── hooks │ └── actor-ref-creator.hook.tsx ├── index.css ├── machines │ ├── inspector │ │ └── inspector.machine.tsx │ ├── resource-picker │ │ ├── resource-picker.context.ts │ │ ├── resource-picker.machine.ts │ │ └── resource-picker.view.tsx │ └── root │ │ ├── root.machine.context.tsx │ │ ├── root.machine.ts │ │ └── root.view.tsx ├── main.tsx ├── providers │ └── polaris.provider.tsx ├── queries.ts ├── shopify.config.ts ├── utils.ts └── vite-env.d.ts ├── tailwind.config.cjs ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.github/workflows/cd.yml: -------------------------------------------------------------------------------- 1 | # Simple workflow for deploying static content to GitHub Pages 2 | name: Deploy static content to Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ['main'] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow one concurrent deployment 19 | concurrency: 20 | group: 'pages' 21 | cancel-in-progress: true 22 | 23 | jobs: 24 | # Single deploy job since we're just deploying 25 | deploy: 26 | environment: 27 | name: github-pages 28 | url: ${{ steps.deployment.outputs.page_url }} 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: "Install pnpm" 32 | uses: pnpm/action-setup@v4 33 | with: 34 | version: 9 35 | - name: Checkout 36 | uses: actions/checkout@v4 37 | - name: Set up Node 38 | uses: actions/setup-node@v4 39 | with: 40 | node-version: 22.x 41 | cache: 'pnpm' 42 | - name: Install dependencies 43 | run: pnpm install --frozen-lockfile 44 | - name: Build 45 | run: pnpm run build 46 | - name: Setup Pages 47 | uses: actions/configure-pages@v4 48 | - name: Upload artifact 49 | uses: actions/upload-pages-artifact@v3 50 | with: 51 | path: './dist' 52 | - name: Deploy to GitHub Pages 53 | id: deployment 54 | uses: actions/deploy-pages@v4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shopify Special Resource Picker 2 | 3 | A Polaris resource picker which can handle any resources, It's intended to explain the usage of Finite State Machines and the Actor Model using XState 4 | 5 | [Video](https://github.com/user-attachments/assets/8fc37aeb-7b32-4c03-bd5e-0eeed9e2a83a) 6 | 7 | You can check [the live demo](https://djang0dev.github.io/special-shopify-resource-picker/), don't forget to click on the inspector 8 | 9 | For more explanations about how I did this, you can check this [thread](https://x.com/djang0_dev/status/1870493077238083829) 10 | 11 | ## Logic 12 | 13 | We use the [Actor Model](https://stately.ai/docs/actor-model) for responsibility delegation: 14 | 15 | ![Actor Model Logic](https://djang0.dev/wp-content/uploads/2024/12/demo-gif.gif) 16 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", 3 | "organizeImports": { 4 | "enabled": true 5 | }, 6 | "files": { 7 | "maxSize": 2097152, 8 | "ignore": [ 9 | "theme.d.ts", 10 | "documentation/plugins", 11 | "documentation/static", 12 | "libs/graphql-codegen", 13 | "libs/translations/src/i18n/**/*" 14 | ] 15 | }, 16 | "formatter": { 17 | "enabled": true, 18 | "indentStyle": "space", 19 | "indentWidth": 2, 20 | "lineWidth": 100 21 | }, 22 | 23 | "javascript": { 24 | "parser": { 25 | "unsafeParameterDecoratorsEnabled": true 26 | }, 27 | "formatter": { 28 | "enabled": true, 29 | "jsxQuoteStyle": "double", 30 | "arrowParentheses": "always", 31 | "quoteStyle": "double", 32 | "semicolons": "asNeeded", 33 | "trailingCommas": "all", 34 | "attributePosition": "auto", 35 | "indentStyle": "space", 36 | "indentWidth": 2, 37 | "bracketSameLine": true, 38 | "quoteProperties": "asNeeded", 39 | "bracketSpacing": true, 40 | "lineWidth": 100 41 | } 42 | }, 43 | "json": { 44 | "formatter": { 45 | "enabled": true 46 | }, 47 | "parser": { 48 | "allowComments": false, 49 | "allowTrailingCommas": false 50 | } 51 | }, 52 | "linter": { 53 | "enabled": true, 54 | "rules": { 55 | "recommended": true, 56 | "a11y": { 57 | "noAriaHiddenOnFocusable": "warn", 58 | "noAutofocus": "warn", 59 | "noBlankTarget": "error", 60 | "noNoninteractiveElementToInteractiveRole": "warn", 61 | "noNoninteractiveTabindex": "warn", 62 | "noPositiveTabindex": "warn", 63 | "noSvgWithoutTitle": "warn", 64 | "useAltText": "warn", 65 | "useButtonType": "warn", 66 | "useHtmlLang": "warn", 67 | "useIframeTitle": "warn", 68 | "useKeyWithClickEvents": "warn", 69 | "useKeyWithMouseEvents": "warn", 70 | "useValidAnchor": "warn" 71 | }, 72 | "nursery": {}, 73 | "complexity": { 74 | "useRegexLiterals": "error", 75 | "noExcessiveCognitiveComplexity": { 76 | "options": { 77 | "maxAllowedComplexity": 18 78 | }, 79 | "level": "error" 80 | }, 81 | "noBannedTypes": "warn", 82 | "noExtraBooleanCast": "warn", 83 | "noForEach": "off", 84 | "noStaticOnlyClass": "error", 85 | "noUselessCatch": "error", 86 | "noUselessConstructor": "error", 87 | "noUselessFragments": "off", 88 | "noUselessRename": "error", 89 | "noUselessSwitchCase": "error", 90 | "useArrowFunction": "error", 91 | "useLiteralKeys": "warn", 92 | "useOptionalChain": "error" 93 | }, 94 | "correctness": { 95 | "noUndeclaredVariables": "warn", 96 | "noConstAssign": "error", 97 | "noChildrenProp": "warn", 98 | "noPrecisionLoss": "error", 99 | "useIsNan": "error", 100 | "noInnerDeclarations": "error", 101 | "noUnusedVariables": "error", 102 | "noUnusedImports": "error", 103 | "noConstantCondition": "error", 104 | "noEmptyPattern": "error", 105 | "noSwitchDeclarations": "error", 106 | "noUnreachable": "error", 107 | "noUnsafeOptionalChaining": "error", 108 | "useExhaustiveDependencies": "error", 109 | "useHookAtTopLevel": "error" 110 | }, 111 | "performance": { 112 | "noAccumulatingSpread": "warn", 113 | "noDelete": "warn" 114 | }, 115 | "security": { 116 | "noGlobalEval": "error", 117 | "noDangerouslySetInnerHtmlWithChildren": "error", 118 | "noDangerouslySetInnerHtml": "error" 119 | }, 120 | "style": { 121 | "useWhile": "warn", 122 | "noVar": "error", 123 | "useImportType": "off", 124 | "noCommaOperator": "error", 125 | "noNonNullAssertion": "warn", 126 | "noParameterAssign": "warn", 127 | "noUnusedTemplateLiteral": "warn", 128 | "noUselessElse": "error", 129 | "useConst": "error", 130 | "useDefaultParameterLast": "warn", 131 | "useSelfClosingElements": "error", 132 | "useSingleVarDeclarator": "error", 133 | "useTemplate": "error" 134 | }, 135 | "suspicious": { 136 | "noDuplicateCase": "error", 137 | "useIsArray": "warn", 138 | "noArrayIndexKey": "warn", 139 | "noAssignInExpressions": "error", 140 | "noAsyncPromiseExecutor": "error", 141 | "noConfusingVoidType": "warn", 142 | "noControlCharactersInRegex": "error", 143 | "noDoubleEquals": "error", 144 | "noDuplicateJsxProps": "error", 145 | "noDuplicateObjectKeys": "error", 146 | "noEmptyInterface": "error", 147 | "noExplicitAny": "warn", 148 | "noFallthroughSwitchClause": "error", 149 | "noGlobalIsNan": "error", 150 | "noImplicitAnyLet": "warn", 151 | "noPrototypeBuiltins": "error", 152 | "noRedeclare": "error", 153 | "noRedundantUseStrict": "error", 154 | "noSelfCompare": "error", 155 | "noShadowRestrictedNames": "warn", 156 | "useDefaultSwitchClauseLast": "error", 157 | "useValidTypeof": "error" 158 | } 159 | } 160 | }, 161 | "vcs": { 162 | "clientKind": "git", 163 | "defaultBranch": "main", 164 | "enabled": true, 165 | "useIgnoreFile": true 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /graphql.config.yml: -------------------------------------------------------------------------------- 1 | projects: 2 | main: 3 | schema: "./schema-storefront.graphql" 4 | documents: "./src/**/*.{tsx,ts}" 5 | exclude: ["**/node_modules/**"] 6 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Special Shopify Resource Picker 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-agnostic-resource-picker-xstate", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "tsc -b && vite build", 9 | "lint": "eslint .", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "graphql-request": "7.1.2", 14 | "@shopify/polaris-icons": "9.3.0", 15 | "remeda": "2.17.4", 16 | "@shopify/polaris": "13.9.1", 17 | "@xstate/react": "4.1.3", 18 | "mutative": "1.1.0", 19 | "react": "^18.3.1", 20 | "react-dom": "^18.3.1", 21 | "react-hot-toast": "2.4.1", 22 | "react-infinite-scroll-hook": "5.0.1", 23 | "xstate": "5.18.2", 24 | "zod": "3.23.8", 25 | "flat": "6.0.1", 26 | "set-value": "4.1.0", 27 | "@statelyai/inspect": "0.4.0" 28 | }, 29 | "devDependencies": { 30 | "@types/set-value": "4.0.3", 31 | "@biomejs/biome": "1.9.4", 32 | "@types/react": "^18.3.12", 33 | "@types/react-dom": "^18.3.1", 34 | "@vitejs/plugin-react": "^4.3.4", 35 | "autoprefixer": "^10.4.20", 36 | "globals": "^15.12.0", 37 | "postcss": "^8.4.49", 38 | "tailwindcss": "^3.4.16", 39 | "typescript": "~5.6.2", 40 | "vite": "^6.0.1" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | '@shopify/polaris': 9 | specifier: 13.9.1 10 | version: 13.9.1(react-dom@18.3.1)(react@18.3.1) 11 | '@shopify/polaris-icons': 12 | specifier: 9.3.0 13 | version: 9.3.0(react@18.3.1) 14 | '@statelyai/inspect': 15 | specifier: 0.4.0 16 | version: 0.4.0(ws@8.18.0)(xstate@5.18.2) 17 | '@xstate/react': 18 | specifier: 4.1.3 19 | version: 4.1.3(@types/react@18.3.16)(react@18.3.1)(xstate@5.18.2) 20 | flat: 21 | specifier: 6.0.1 22 | version: 6.0.1 23 | graphql-request: 24 | specifier: 7.1.2 25 | version: 7.1.2(graphql@16.9.0) 26 | mutative: 27 | specifier: 1.1.0 28 | version: 1.1.0 29 | react: 30 | specifier: ^18.3.1 31 | version: 18.3.1 32 | react-dom: 33 | specifier: ^18.3.1 34 | version: 18.3.1(react@18.3.1) 35 | react-hot-toast: 36 | specifier: 2.4.1 37 | version: 2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@18.3.1) 38 | react-infinite-scroll-hook: 39 | specifier: 5.0.1 40 | version: 5.0.1(react-dom@18.3.1)(react@18.3.1) 41 | remeda: 42 | specifier: 2.17.4 43 | version: 2.17.4 44 | set-value: 45 | specifier: 4.1.0 46 | version: 4.1.0 47 | xstate: 48 | specifier: 5.18.2 49 | version: 5.18.2 50 | zod: 51 | specifier: 3.23.8 52 | version: 3.23.8 53 | 54 | devDependencies: 55 | '@biomejs/biome': 56 | specifier: 1.9.4 57 | version: 1.9.4 58 | '@types/react': 59 | specifier: ^18.3.12 60 | version: 18.3.16 61 | '@types/react-dom': 62 | specifier: ^18.3.1 63 | version: 18.3.5(@types/react@18.3.16) 64 | '@types/set-value': 65 | specifier: 4.0.3 66 | version: 4.0.3 67 | '@vitejs/plugin-react': 68 | specifier: ^4.3.4 69 | version: 4.3.4(vite@6.0.3) 70 | autoprefixer: 71 | specifier: ^10.4.20 72 | version: 10.4.20(postcss@8.4.49) 73 | globals: 74 | specifier: ^15.12.0 75 | version: 15.13.0 76 | postcss: 77 | specifier: ^8.4.49 78 | version: 8.4.49 79 | tailwindcss: 80 | specifier: ^3.4.16 81 | version: 3.4.16 82 | typescript: 83 | specifier: ~5.6.2 84 | version: 5.6.3 85 | vite: 86 | specifier: ^6.0.1 87 | version: 6.0.3 88 | 89 | packages: 90 | 91 | /@alloc/quick-lru@5.2.0: 92 | resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} 93 | engines: {node: '>=10'} 94 | dev: true 95 | 96 | /@ampproject/remapping@2.3.0: 97 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} 98 | engines: {node: '>=6.0.0'} 99 | dependencies: 100 | '@jridgewell/gen-mapping': 0.3.8 101 | '@jridgewell/trace-mapping': 0.3.25 102 | dev: true 103 | 104 | /@babel/code-frame@7.26.2: 105 | resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} 106 | engines: {node: '>=6.9.0'} 107 | dependencies: 108 | '@babel/helper-validator-identifier': 7.25.9 109 | js-tokens: 4.0.0 110 | picocolors: 1.1.1 111 | dev: true 112 | 113 | /@babel/compat-data@7.26.3: 114 | resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} 115 | engines: {node: '>=6.9.0'} 116 | dev: true 117 | 118 | /@babel/core@7.26.0: 119 | resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} 120 | engines: {node: '>=6.9.0'} 121 | dependencies: 122 | '@ampproject/remapping': 2.3.0 123 | '@babel/code-frame': 7.26.2 124 | '@babel/generator': 7.26.3 125 | '@babel/helper-compilation-targets': 7.25.9 126 | '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) 127 | '@babel/helpers': 7.26.0 128 | '@babel/parser': 7.26.3 129 | '@babel/template': 7.25.9 130 | '@babel/traverse': 7.26.4 131 | '@babel/types': 7.26.3 132 | convert-source-map: 2.0.0 133 | debug: 4.4.0 134 | gensync: 1.0.0-beta.2 135 | json5: 2.2.3 136 | semver: 6.3.1 137 | transitivePeerDependencies: 138 | - supports-color 139 | dev: true 140 | 141 | /@babel/generator@7.26.3: 142 | resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==} 143 | engines: {node: '>=6.9.0'} 144 | dependencies: 145 | '@babel/parser': 7.26.3 146 | '@babel/types': 7.26.3 147 | '@jridgewell/gen-mapping': 0.3.8 148 | '@jridgewell/trace-mapping': 0.3.25 149 | jsesc: 3.1.0 150 | dev: true 151 | 152 | /@babel/helper-compilation-targets@7.25.9: 153 | resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} 154 | engines: {node: '>=6.9.0'} 155 | dependencies: 156 | '@babel/compat-data': 7.26.3 157 | '@babel/helper-validator-option': 7.25.9 158 | browserslist: 4.24.2 159 | lru-cache: 5.1.1 160 | semver: 6.3.1 161 | dev: true 162 | 163 | /@babel/helper-module-imports@7.25.9: 164 | resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} 165 | engines: {node: '>=6.9.0'} 166 | dependencies: 167 | '@babel/traverse': 7.26.4 168 | '@babel/types': 7.26.3 169 | transitivePeerDependencies: 170 | - supports-color 171 | dev: true 172 | 173 | /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0): 174 | resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} 175 | engines: {node: '>=6.9.0'} 176 | peerDependencies: 177 | '@babel/core': ^7.0.0 178 | dependencies: 179 | '@babel/core': 7.26.0 180 | '@babel/helper-module-imports': 7.25.9 181 | '@babel/helper-validator-identifier': 7.25.9 182 | '@babel/traverse': 7.26.4 183 | transitivePeerDependencies: 184 | - supports-color 185 | dev: true 186 | 187 | /@babel/helper-plugin-utils@7.25.9: 188 | resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} 189 | engines: {node: '>=6.9.0'} 190 | dev: true 191 | 192 | /@babel/helper-string-parser@7.25.9: 193 | resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} 194 | engines: {node: '>=6.9.0'} 195 | dev: true 196 | 197 | /@babel/helper-validator-identifier@7.25.9: 198 | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} 199 | engines: {node: '>=6.9.0'} 200 | dev: true 201 | 202 | /@babel/helper-validator-option@7.25.9: 203 | resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} 204 | engines: {node: '>=6.9.0'} 205 | dev: true 206 | 207 | /@babel/helpers@7.26.0: 208 | resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} 209 | engines: {node: '>=6.9.0'} 210 | dependencies: 211 | '@babel/template': 7.25.9 212 | '@babel/types': 7.26.3 213 | dev: true 214 | 215 | /@babel/parser@7.26.3: 216 | resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} 217 | engines: {node: '>=6.0.0'} 218 | hasBin: true 219 | dependencies: 220 | '@babel/types': 7.26.3 221 | dev: true 222 | 223 | /@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0): 224 | resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} 225 | engines: {node: '>=6.9.0'} 226 | peerDependencies: 227 | '@babel/core': ^7.0.0-0 228 | dependencies: 229 | '@babel/core': 7.26.0 230 | '@babel/helper-plugin-utils': 7.25.9 231 | dev: true 232 | 233 | /@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0): 234 | resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} 235 | engines: {node: '>=6.9.0'} 236 | peerDependencies: 237 | '@babel/core': ^7.0.0-0 238 | dependencies: 239 | '@babel/core': 7.26.0 240 | '@babel/helper-plugin-utils': 7.25.9 241 | dev: true 242 | 243 | /@babel/runtime@7.26.0: 244 | resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} 245 | engines: {node: '>=6.9.0'} 246 | dependencies: 247 | regenerator-runtime: 0.14.1 248 | dev: false 249 | 250 | /@babel/template@7.25.9: 251 | resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} 252 | engines: {node: '>=6.9.0'} 253 | dependencies: 254 | '@babel/code-frame': 7.26.2 255 | '@babel/parser': 7.26.3 256 | '@babel/types': 7.26.3 257 | dev: true 258 | 259 | /@babel/traverse@7.26.4: 260 | resolution: {integrity: sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==} 261 | engines: {node: '>=6.9.0'} 262 | dependencies: 263 | '@babel/code-frame': 7.26.2 264 | '@babel/generator': 7.26.3 265 | '@babel/parser': 7.26.3 266 | '@babel/template': 7.25.9 267 | '@babel/types': 7.26.3 268 | debug: 4.4.0 269 | globals: 11.12.0 270 | transitivePeerDependencies: 271 | - supports-color 272 | dev: true 273 | 274 | /@babel/types@7.26.3: 275 | resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} 276 | engines: {node: '>=6.9.0'} 277 | dependencies: 278 | '@babel/helper-string-parser': 7.25.9 279 | '@babel/helper-validator-identifier': 7.25.9 280 | dev: true 281 | 282 | /@biomejs/biome@1.9.4: 283 | resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} 284 | engines: {node: '>=14.21.3'} 285 | hasBin: true 286 | requiresBuild: true 287 | optionalDependencies: 288 | '@biomejs/cli-darwin-arm64': 1.9.4 289 | '@biomejs/cli-darwin-x64': 1.9.4 290 | '@biomejs/cli-linux-arm64': 1.9.4 291 | '@biomejs/cli-linux-arm64-musl': 1.9.4 292 | '@biomejs/cli-linux-x64': 1.9.4 293 | '@biomejs/cli-linux-x64-musl': 1.9.4 294 | '@biomejs/cli-win32-arm64': 1.9.4 295 | '@biomejs/cli-win32-x64': 1.9.4 296 | dev: true 297 | 298 | /@biomejs/cli-darwin-arm64@1.9.4: 299 | resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} 300 | engines: {node: '>=14.21.3'} 301 | cpu: [arm64] 302 | os: [darwin] 303 | requiresBuild: true 304 | dev: true 305 | optional: true 306 | 307 | /@biomejs/cli-darwin-x64@1.9.4: 308 | resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} 309 | engines: {node: '>=14.21.3'} 310 | cpu: [x64] 311 | os: [darwin] 312 | requiresBuild: true 313 | dev: true 314 | optional: true 315 | 316 | /@biomejs/cli-linux-arm64-musl@1.9.4: 317 | resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} 318 | engines: {node: '>=14.21.3'} 319 | cpu: [arm64] 320 | os: [linux] 321 | requiresBuild: true 322 | dev: true 323 | optional: true 324 | 325 | /@biomejs/cli-linux-arm64@1.9.4: 326 | resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} 327 | engines: {node: '>=14.21.3'} 328 | cpu: [arm64] 329 | os: [linux] 330 | requiresBuild: true 331 | dev: true 332 | optional: true 333 | 334 | /@biomejs/cli-linux-x64-musl@1.9.4: 335 | resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} 336 | engines: {node: '>=14.21.3'} 337 | cpu: [x64] 338 | os: [linux] 339 | requiresBuild: true 340 | dev: true 341 | optional: true 342 | 343 | /@biomejs/cli-linux-x64@1.9.4: 344 | resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} 345 | engines: {node: '>=14.21.3'} 346 | cpu: [x64] 347 | os: [linux] 348 | requiresBuild: true 349 | dev: true 350 | optional: true 351 | 352 | /@biomejs/cli-win32-arm64@1.9.4: 353 | resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} 354 | engines: {node: '>=14.21.3'} 355 | cpu: [arm64] 356 | os: [win32] 357 | requiresBuild: true 358 | dev: true 359 | optional: true 360 | 361 | /@biomejs/cli-win32-x64@1.9.4: 362 | resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} 363 | engines: {node: '>=14.21.3'} 364 | cpu: [x64] 365 | os: [win32] 366 | requiresBuild: true 367 | dev: true 368 | optional: true 369 | 370 | /@esbuild/aix-ppc64@0.24.0: 371 | resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} 372 | engines: {node: '>=18'} 373 | cpu: [ppc64] 374 | os: [aix] 375 | requiresBuild: true 376 | dev: true 377 | optional: true 378 | 379 | /@esbuild/android-arm64@0.24.0: 380 | resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} 381 | engines: {node: '>=18'} 382 | cpu: [arm64] 383 | os: [android] 384 | requiresBuild: true 385 | dev: true 386 | optional: true 387 | 388 | /@esbuild/android-arm@0.24.0: 389 | resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} 390 | engines: {node: '>=18'} 391 | cpu: [arm] 392 | os: [android] 393 | requiresBuild: true 394 | dev: true 395 | optional: true 396 | 397 | /@esbuild/android-x64@0.24.0: 398 | resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} 399 | engines: {node: '>=18'} 400 | cpu: [x64] 401 | os: [android] 402 | requiresBuild: true 403 | dev: true 404 | optional: true 405 | 406 | /@esbuild/darwin-arm64@0.24.0: 407 | resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} 408 | engines: {node: '>=18'} 409 | cpu: [arm64] 410 | os: [darwin] 411 | requiresBuild: true 412 | dev: true 413 | optional: true 414 | 415 | /@esbuild/darwin-x64@0.24.0: 416 | resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} 417 | engines: {node: '>=18'} 418 | cpu: [x64] 419 | os: [darwin] 420 | requiresBuild: true 421 | dev: true 422 | optional: true 423 | 424 | /@esbuild/freebsd-arm64@0.24.0: 425 | resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} 426 | engines: {node: '>=18'} 427 | cpu: [arm64] 428 | os: [freebsd] 429 | requiresBuild: true 430 | dev: true 431 | optional: true 432 | 433 | /@esbuild/freebsd-x64@0.24.0: 434 | resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} 435 | engines: {node: '>=18'} 436 | cpu: [x64] 437 | os: [freebsd] 438 | requiresBuild: true 439 | dev: true 440 | optional: true 441 | 442 | /@esbuild/linux-arm64@0.24.0: 443 | resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} 444 | engines: {node: '>=18'} 445 | cpu: [arm64] 446 | os: [linux] 447 | requiresBuild: true 448 | dev: true 449 | optional: true 450 | 451 | /@esbuild/linux-arm@0.24.0: 452 | resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} 453 | engines: {node: '>=18'} 454 | cpu: [arm] 455 | os: [linux] 456 | requiresBuild: true 457 | dev: true 458 | optional: true 459 | 460 | /@esbuild/linux-ia32@0.24.0: 461 | resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} 462 | engines: {node: '>=18'} 463 | cpu: [ia32] 464 | os: [linux] 465 | requiresBuild: true 466 | dev: true 467 | optional: true 468 | 469 | /@esbuild/linux-loong64@0.24.0: 470 | resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} 471 | engines: {node: '>=18'} 472 | cpu: [loong64] 473 | os: [linux] 474 | requiresBuild: true 475 | dev: true 476 | optional: true 477 | 478 | /@esbuild/linux-mips64el@0.24.0: 479 | resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} 480 | engines: {node: '>=18'} 481 | cpu: [mips64el] 482 | os: [linux] 483 | requiresBuild: true 484 | dev: true 485 | optional: true 486 | 487 | /@esbuild/linux-ppc64@0.24.0: 488 | resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} 489 | engines: {node: '>=18'} 490 | cpu: [ppc64] 491 | os: [linux] 492 | requiresBuild: true 493 | dev: true 494 | optional: true 495 | 496 | /@esbuild/linux-riscv64@0.24.0: 497 | resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} 498 | engines: {node: '>=18'} 499 | cpu: [riscv64] 500 | os: [linux] 501 | requiresBuild: true 502 | dev: true 503 | optional: true 504 | 505 | /@esbuild/linux-s390x@0.24.0: 506 | resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} 507 | engines: {node: '>=18'} 508 | cpu: [s390x] 509 | os: [linux] 510 | requiresBuild: true 511 | dev: true 512 | optional: true 513 | 514 | /@esbuild/linux-x64@0.24.0: 515 | resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} 516 | engines: {node: '>=18'} 517 | cpu: [x64] 518 | os: [linux] 519 | requiresBuild: true 520 | dev: true 521 | optional: true 522 | 523 | /@esbuild/netbsd-x64@0.24.0: 524 | resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} 525 | engines: {node: '>=18'} 526 | cpu: [x64] 527 | os: [netbsd] 528 | requiresBuild: true 529 | dev: true 530 | optional: true 531 | 532 | /@esbuild/openbsd-arm64@0.24.0: 533 | resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} 534 | engines: {node: '>=18'} 535 | cpu: [arm64] 536 | os: [openbsd] 537 | requiresBuild: true 538 | dev: true 539 | optional: true 540 | 541 | /@esbuild/openbsd-x64@0.24.0: 542 | resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} 543 | engines: {node: '>=18'} 544 | cpu: [x64] 545 | os: [openbsd] 546 | requiresBuild: true 547 | dev: true 548 | optional: true 549 | 550 | /@esbuild/sunos-x64@0.24.0: 551 | resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} 552 | engines: {node: '>=18'} 553 | cpu: [x64] 554 | os: [sunos] 555 | requiresBuild: true 556 | dev: true 557 | optional: true 558 | 559 | /@esbuild/win32-arm64@0.24.0: 560 | resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} 561 | engines: {node: '>=18'} 562 | cpu: [arm64] 563 | os: [win32] 564 | requiresBuild: true 565 | dev: true 566 | optional: true 567 | 568 | /@esbuild/win32-ia32@0.24.0: 569 | resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} 570 | engines: {node: '>=18'} 571 | cpu: [ia32] 572 | os: [win32] 573 | requiresBuild: true 574 | dev: true 575 | optional: true 576 | 577 | /@esbuild/win32-x64@0.24.0: 578 | resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} 579 | engines: {node: '>=18'} 580 | cpu: [x64] 581 | os: [win32] 582 | requiresBuild: true 583 | dev: true 584 | optional: true 585 | 586 | /@graphql-typed-document-node/core@3.2.0(graphql@16.9.0): 587 | resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} 588 | peerDependencies: 589 | graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 590 | dependencies: 591 | graphql: 16.9.0 592 | dev: false 593 | 594 | /@isaacs/cliui@8.0.2: 595 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 596 | engines: {node: '>=12'} 597 | dependencies: 598 | string-width: 5.1.2 599 | string-width-cjs: /string-width@4.2.3 600 | strip-ansi: 7.1.0 601 | strip-ansi-cjs: /strip-ansi@6.0.1 602 | wrap-ansi: 8.1.0 603 | wrap-ansi-cjs: /wrap-ansi@7.0.0 604 | dev: true 605 | 606 | /@jridgewell/gen-mapping@0.3.8: 607 | resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} 608 | engines: {node: '>=6.0.0'} 609 | dependencies: 610 | '@jridgewell/set-array': 1.2.1 611 | '@jridgewell/sourcemap-codec': 1.5.0 612 | '@jridgewell/trace-mapping': 0.3.25 613 | dev: true 614 | 615 | /@jridgewell/resolve-uri@3.1.2: 616 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 617 | engines: {node: '>=6.0.0'} 618 | dev: true 619 | 620 | /@jridgewell/set-array@1.2.1: 621 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 622 | engines: {node: '>=6.0.0'} 623 | dev: true 624 | 625 | /@jridgewell/sourcemap-codec@1.5.0: 626 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 627 | dev: true 628 | 629 | /@jridgewell/trace-mapping@0.3.25: 630 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 631 | dependencies: 632 | '@jridgewell/resolve-uri': 3.1.2 633 | '@jridgewell/sourcemap-codec': 1.5.0 634 | dev: true 635 | 636 | /@nodelib/fs.scandir@2.1.5: 637 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 638 | engines: {node: '>= 8'} 639 | dependencies: 640 | '@nodelib/fs.stat': 2.0.5 641 | run-parallel: 1.2.0 642 | dev: true 643 | 644 | /@nodelib/fs.stat@2.0.5: 645 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 646 | engines: {node: '>= 8'} 647 | dev: true 648 | 649 | /@nodelib/fs.walk@1.2.8: 650 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 651 | engines: {node: '>= 8'} 652 | dependencies: 653 | '@nodelib/fs.scandir': 2.1.5 654 | fastq: 1.17.1 655 | dev: true 656 | 657 | /@pkgjs/parseargs@0.11.0: 658 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 659 | engines: {node: '>=14'} 660 | requiresBuild: true 661 | dev: true 662 | optional: true 663 | 664 | /@rollup/rollup-android-arm-eabi@4.28.1: 665 | resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==} 666 | cpu: [arm] 667 | os: [android] 668 | requiresBuild: true 669 | dev: true 670 | optional: true 671 | 672 | /@rollup/rollup-android-arm64@4.28.1: 673 | resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==} 674 | cpu: [arm64] 675 | os: [android] 676 | requiresBuild: true 677 | dev: true 678 | optional: true 679 | 680 | /@rollup/rollup-darwin-arm64@4.28.1: 681 | resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==} 682 | cpu: [arm64] 683 | os: [darwin] 684 | requiresBuild: true 685 | dev: true 686 | optional: true 687 | 688 | /@rollup/rollup-darwin-x64@4.28.1: 689 | resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==} 690 | cpu: [x64] 691 | os: [darwin] 692 | requiresBuild: true 693 | dev: true 694 | optional: true 695 | 696 | /@rollup/rollup-freebsd-arm64@4.28.1: 697 | resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==} 698 | cpu: [arm64] 699 | os: [freebsd] 700 | requiresBuild: true 701 | dev: true 702 | optional: true 703 | 704 | /@rollup/rollup-freebsd-x64@4.28.1: 705 | resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==} 706 | cpu: [x64] 707 | os: [freebsd] 708 | requiresBuild: true 709 | dev: true 710 | optional: true 711 | 712 | /@rollup/rollup-linux-arm-gnueabihf@4.28.1: 713 | resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==} 714 | cpu: [arm] 715 | os: [linux] 716 | requiresBuild: true 717 | dev: true 718 | optional: true 719 | 720 | /@rollup/rollup-linux-arm-musleabihf@4.28.1: 721 | resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==} 722 | cpu: [arm] 723 | os: [linux] 724 | requiresBuild: true 725 | dev: true 726 | optional: true 727 | 728 | /@rollup/rollup-linux-arm64-gnu@4.28.1: 729 | resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==} 730 | cpu: [arm64] 731 | os: [linux] 732 | requiresBuild: true 733 | dev: true 734 | optional: true 735 | 736 | /@rollup/rollup-linux-arm64-musl@4.28.1: 737 | resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==} 738 | cpu: [arm64] 739 | os: [linux] 740 | requiresBuild: true 741 | dev: true 742 | optional: true 743 | 744 | /@rollup/rollup-linux-loongarch64-gnu@4.28.1: 745 | resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==} 746 | cpu: [loong64] 747 | os: [linux] 748 | requiresBuild: true 749 | dev: true 750 | optional: true 751 | 752 | /@rollup/rollup-linux-powerpc64le-gnu@4.28.1: 753 | resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==} 754 | cpu: [ppc64] 755 | os: [linux] 756 | requiresBuild: true 757 | dev: true 758 | optional: true 759 | 760 | /@rollup/rollup-linux-riscv64-gnu@4.28.1: 761 | resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==} 762 | cpu: [riscv64] 763 | os: [linux] 764 | requiresBuild: true 765 | dev: true 766 | optional: true 767 | 768 | /@rollup/rollup-linux-s390x-gnu@4.28.1: 769 | resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==} 770 | cpu: [s390x] 771 | os: [linux] 772 | requiresBuild: true 773 | dev: true 774 | optional: true 775 | 776 | /@rollup/rollup-linux-x64-gnu@4.28.1: 777 | resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==} 778 | cpu: [x64] 779 | os: [linux] 780 | requiresBuild: true 781 | dev: true 782 | optional: true 783 | 784 | /@rollup/rollup-linux-x64-musl@4.28.1: 785 | resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==} 786 | cpu: [x64] 787 | os: [linux] 788 | requiresBuild: true 789 | dev: true 790 | optional: true 791 | 792 | /@rollup/rollup-win32-arm64-msvc@4.28.1: 793 | resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==} 794 | cpu: [arm64] 795 | os: [win32] 796 | requiresBuild: true 797 | dev: true 798 | optional: true 799 | 800 | /@rollup/rollup-win32-ia32-msvc@4.28.1: 801 | resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==} 802 | cpu: [ia32] 803 | os: [win32] 804 | requiresBuild: true 805 | dev: true 806 | optional: true 807 | 808 | /@rollup/rollup-win32-x64-msvc@4.28.1: 809 | resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==} 810 | cpu: [x64] 811 | os: [win32] 812 | requiresBuild: true 813 | dev: true 814 | optional: true 815 | 816 | /@shopify/polaris-icons@9.3.0(react@18.3.1): 817 | resolution: {integrity: sha512-fnH5Lcd3WFZNjlxGYGNtnjeq3P2xonRV8vChW4PqBfxdKlY/GQ/3/rIuxHzIgmLL0zukeZUaqERUN0lwSU+Xmg==} 818 | engines: {node: '>=20.10.0'} 819 | peerDependencies: 820 | react: '*' 821 | dependencies: 822 | react: 18.3.1 823 | dev: false 824 | 825 | /@shopify/polaris-tokens@9.4.0: 826 | resolution: {integrity: sha512-jnCNxq9+XfWP9ijkvSsgQH5o3PeYgfWo4/zymoO+AeJvyngL+4LvlZ/nofvYj9DXLo74taTk05xui9qt22Zy2Q==} 827 | engines: {node: '>=20.10.0'} 828 | dependencies: 829 | deepmerge: 4.3.1 830 | dev: false 831 | 832 | /@shopify/polaris@13.9.1(react-dom@18.3.1)(react@18.3.1): 833 | resolution: {integrity: sha512-jSBEDP3LPZlPWJbtwTLdW72K1LS73ocB7x3VXzbi1DvpxUcmVp3K1YxhdKGEKmwHAkcBqIvZCrVNS2jcaTBmhQ==} 834 | engines: {node: '>=20.10.0'} 835 | peerDependencies: 836 | react: ^18.0.0 837 | react-dom: ^18.0.0 838 | dependencies: 839 | '@shopify/polaris-icons': 9.3.0(react@18.3.1) 840 | '@shopify/polaris-tokens': 9.4.0 841 | '@types/react': 18.3.16 842 | '@types/react-dom': 18.3.5(@types/react@18.3.16) 843 | '@types/react-transition-group': 4.4.12(@types/react@18.3.16) 844 | react: 18.3.1 845 | react-dom: 18.3.1(react@18.3.1) 846 | react-fast-compare: 3.2.2 847 | react-transition-group: 4.4.5(react-dom@18.3.1)(react@18.3.1) 848 | dev: false 849 | 850 | /@statelyai/inspect@0.4.0(ws@8.18.0)(xstate@5.18.2): 851 | resolution: {integrity: sha512-VxQldRlKYcu6rzLY83RSXVwMYexkH6hNx85B89YWYyXYWtNGaWHFCwV7a/Kz8FFPeUz8EKVAnyMOg2kNpn07wQ==} 852 | peerDependencies: 853 | xstate: ^5.5.1 854 | dependencies: 855 | fast-safe-stringify: 2.1.1 856 | isomorphic-ws: 5.0.0(ws@8.18.0) 857 | partysocket: 0.0.25 858 | safe-stable-stringify: 2.5.0 859 | superjson: 1.13.3 860 | uuid: 9.0.1 861 | xstate: 5.18.2 862 | transitivePeerDependencies: 863 | - ws 864 | dev: false 865 | 866 | /@types/babel__core@7.20.5: 867 | resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} 868 | dependencies: 869 | '@babel/parser': 7.26.3 870 | '@babel/types': 7.26.3 871 | '@types/babel__generator': 7.6.8 872 | '@types/babel__template': 7.4.4 873 | '@types/babel__traverse': 7.20.6 874 | dev: true 875 | 876 | /@types/babel__generator@7.6.8: 877 | resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} 878 | dependencies: 879 | '@babel/types': 7.26.3 880 | dev: true 881 | 882 | /@types/babel__template@7.4.4: 883 | resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} 884 | dependencies: 885 | '@babel/parser': 7.26.3 886 | '@babel/types': 7.26.3 887 | dev: true 888 | 889 | /@types/babel__traverse@7.20.6: 890 | resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} 891 | dependencies: 892 | '@babel/types': 7.26.3 893 | dev: true 894 | 895 | /@types/estree@1.0.6: 896 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 897 | dev: true 898 | 899 | /@types/prop-types@15.7.14: 900 | resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} 901 | 902 | /@types/react-dom@18.3.5(@types/react@18.3.16): 903 | resolution: {integrity: sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==} 904 | peerDependencies: 905 | '@types/react': ^18.0.0 906 | dependencies: 907 | '@types/react': 18.3.16 908 | 909 | /@types/react-transition-group@4.4.12(@types/react@18.3.16): 910 | resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==} 911 | peerDependencies: 912 | '@types/react': '*' 913 | dependencies: 914 | '@types/react': 18.3.16 915 | dev: false 916 | 917 | /@types/react@18.3.16: 918 | resolution: {integrity: sha512-oh8AMIC4Y2ciKufU8hnKgs+ufgbA/dhPTACaZPM86AbwX9QwnFtSoPWEeRUj8fge+v6kFt78BXcDhAU1SrrAsw==} 919 | dependencies: 920 | '@types/prop-types': 15.7.14 921 | csstype: 3.1.3 922 | 923 | /@types/set-value@4.0.3: 924 | resolution: {integrity: sha512-tSuUcLl6kMzI+l0gG7FZ04xbIcynxNIYgWFj91LPAvRcn7W3L1EveXNdVjqFDgAZPjY1qCOsm8Sb1C70SxAPHw==} 925 | dev: true 926 | 927 | /@vitejs/plugin-react@4.3.4(vite@6.0.3): 928 | resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} 929 | engines: {node: ^14.18.0 || >=16.0.0} 930 | peerDependencies: 931 | vite: ^4.2.0 || ^5.0.0 || ^6.0.0 932 | dependencies: 933 | '@babel/core': 7.26.0 934 | '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0) 935 | '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0) 936 | '@types/babel__core': 7.20.5 937 | react-refresh: 0.14.2 938 | vite: 6.0.3 939 | transitivePeerDependencies: 940 | - supports-color 941 | dev: true 942 | 943 | /@xstate/react@4.1.3(@types/react@18.3.16)(react@18.3.1)(xstate@5.18.2): 944 | resolution: {integrity: sha512-zhE+ZfrcCR87bu71Rkh5Z5ruZBivR/7uD/dkelzJqjQdI45IZc9DqTI8lL4Cg5+VN2p5k86KxDsusqW1kW11Tg==} 945 | peerDependencies: 946 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 947 | xstate: ^5.18.2 948 | peerDependenciesMeta: 949 | xstate: 950 | optional: true 951 | dependencies: 952 | react: 18.3.1 953 | use-isomorphic-layout-effect: 1.2.0(@types/react@18.3.16)(react@18.3.1) 954 | use-sync-external-store: 1.4.0(react@18.3.1) 955 | xstate: 5.18.2 956 | transitivePeerDependencies: 957 | - '@types/react' 958 | dev: false 959 | 960 | /ansi-regex@5.0.1: 961 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 962 | engines: {node: '>=8'} 963 | dev: true 964 | 965 | /ansi-regex@6.1.0: 966 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 967 | engines: {node: '>=12'} 968 | dev: true 969 | 970 | /ansi-styles@4.3.0: 971 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 972 | engines: {node: '>=8'} 973 | dependencies: 974 | color-convert: 2.0.1 975 | dev: true 976 | 977 | /ansi-styles@6.2.1: 978 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 979 | engines: {node: '>=12'} 980 | dev: true 981 | 982 | /any-promise@1.3.0: 983 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 984 | dev: true 985 | 986 | /anymatch@3.1.3: 987 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 988 | engines: {node: '>= 8'} 989 | dependencies: 990 | normalize-path: 3.0.0 991 | picomatch: 2.3.1 992 | dev: true 993 | 994 | /arg@5.0.2: 995 | resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} 996 | dev: true 997 | 998 | /autoprefixer@10.4.20(postcss@8.4.49): 999 | resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} 1000 | engines: {node: ^10 || ^12 || >=14} 1001 | hasBin: true 1002 | peerDependencies: 1003 | postcss: ^8.1.0 1004 | dependencies: 1005 | browserslist: 4.24.2 1006 | caniuse-lite: 1.0.30001688 1007 | fraction.js: 4.3.7 1008 | normalize-range: 0.1.2 1009 | picocolors: 1.1.1 1010 | postcss: 8.4.49 1011 | postcss-value-parser: 4.2.0 1012 | dev: true 1013 | 1014 | /balanced-match@1.0.2: 1015 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 1016 | dev: true 1017 | 1018 | /binary-extensions@2.3.0: 1019 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 1020 | engines: {node: '>=8'} 1021 | dev: true 1022 | 1023 | /brace-expansion@2.0.1: 1024 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 1025 | dependencies: 1026 | balanced-match: 1.0.2 1027 | dev: true 1028 | 1029 | /braces@3.0.3: 1030 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 1031 | engines: {node: '>=8'} 1032 | dependencies: 1033 | fill-range: 7.1.1 1034 | dev: true 1035 | 1036 | /browserslist@4.24.2: 1037 | resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} 1038 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 1039 | hasBin: true 1040 | dependencies: 1041 | caniuse-lite: 1.0.30001688 1042 | electron-to-chromium: 1.5.73 1043 | node-releases: 2.0.19 1044 | update-browserslist-db: 1.1.1(browserslist@4.24.2) 1045 | dev: true 1046 | 1047 | /camelcase-css@2.0.1: 1048 | resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} 1049 | engines: {node: '>= 6'} 1050 | dev: true 1051 | 1052 | /caniuse-lite@1.0.30001688: 1053 | resolution: {integrity: sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA==} 1054 | dev: true 1055 | 1056 | /chokidar@3.6.0: 1057 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 1058 | engines: {node: '>= 8.10.0'} 1059 | dependencies: 1060 | anymatch: 3.1.3 1061 | braces: 3.0.3 1062 | glob-parent: 5.1.2 1063 | is-binary-path: 2.1.0 1064 | is-glob: 4.0.3 1065 | normalize-path: 3.0.0 1066 | readdirp: 3.6.0 1067 | optionalDependencies: 1068 | fsevents: 2.3.3 1069 | dev: true 1070 | 1071 | /color-convert@2.0.1: 1072 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 1073 | engines: {node: '>=7.0.0'} 1074 | dependencies: 1075 | color-name: 1.1.4 1076 | dev: true 1077 | 1078 | /color-name@1.1.4: 1079 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 1080 | dev: true 1081 | 1082 | /commander@4.1.1: 1083 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 1084 | engines: {node: '>= 6'} 1085 | dev: true 1086 | 1087 | /convert-source-map@2.0.0: 1088 | resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} 1089 | dev: true 1090 | 1091 | /copy-anything@3.0.5: 1092 | resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} 1093 | engines: {node: '>=12.13'} 1094 | dependencies: 1095 | is-what: 4.1.16 1096 | dev: false 1097 | 1098 | /cross-spawn@7.0.6: 1099 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 1100 | engines: {node: '>= 8'} 1101 | dependencies: 1102 | path-key: 3.1.1 1103 | shebang-command: 2.0.0 1104 | which: 2.0.2 1105 | dev: true 1106 | 1107 | /cssesc@3.0.0: 1108 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} 1109 | engines: {node: '>=4'} 1110 | hasBin: true 1111 | dev: true 1112 | 1113 | /csstype@3.1.3: 1114 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 1115 | 1116 | /debug@4.4.0: 1117 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 1118 | engines: {node: '>=6.0'} 1119 | peerDependencies: 1120 | supports-color: '*' 1121 | peerDependenciesMeta: 1122 | supports-color: 1123 | optional: true 1124 | dependencies: 1125 | ms: 2.1.3 1126 | dev: true 1127 | 1128 | /deepmerge@4.3.1: 1129 | resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} 1130 | engines: {node: '>=0.10.0'} 1131 | dev: false 1132 | 1133 | /didyoumean@1.2.2: 1134 | resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} 1135 | dev: true 1136 | 1137 | /dlv@1.1.3: 1138 | resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} 1139 | dev: true 1140 | 1141 | /dom-helpers@5.2.1: 1142 | resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} 1143 | dependencies: 1144 | '@babel/runtime': 7.26.0 1145 | csstype: 3.1.3 1146 | dev: false 1147 | 1148 | /eastasianwidth@0.2.0: 1149 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 1150 | dev: true 1151 | 1152 | /electron-to-chromium@1.5.73: 1153 | resolution: {integrity: sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg==} 1154 | dev: true 1155 | 1156 | /emoji-regex@8.0.0: 1157 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 1158 | dev: true 1159 | 1160 | /emoji-regex@9.2.2: 1161 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 1162 | dev: true 1163 | 1164 | /esbuild@0.24.0: 1165 | resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} 1166 | engines: {node: '>=18'} 1167 | hasBin: true 1168 | requiresBuild: true 1169 | optionalDependencies: 1170 | '@esbuild/aix-ppc64': 0.24.0 1171 | '@esbuild/android-arm': 0.24.0 1172 | '@esbuild/android-arm64': 0.24.0 1173 | '@esbuild/android-x64': 0.24.0 1174 | '@esbuild/darwin-arm64': 0.24.0 1175 | '@esbuild/darwin-x64': 0.24.0 1176 | '@esbuild/freebsd-arm64': 0.24.0 1177 | '@esbuild/freebsd-x64': 0.24.0 1178 | '@esbuild/linux-arm': 0.24.0 1179 | '@esbuild/linux-arm64': 0.24.0 1180 | '@esbuild/linux-ia32': 0.24.0 1181 | '@esbuild/linux-loong64': 0.24.0 1182 | '@esbuild/linux-mips64el': 0.24.0 1183 | '@esbuild/linux-ppc64': 0.24.0 1184 | '@esbuild/linux-riscv64': 0.24.0 1185 | '@esbuild/linux-s390x': 0.24.0 1186 | '@esbuild/linux-x64': 0.24.0 1187 | '@esbuild/netbsd-x64': 0.24.0 1188 | '@esbuild/openbsd-arm64': 0.24.0 1189 | '@esbuild/openbsd-x64': 0.24.0 1190 | '@esbuild/sunos-x64': 0.24.0 1191 | '@esbuild/win32-arm64': 0.24.0 1192 | '@esbuild/win32-ia32': 0.24.0 1193 | '@esbuild/win32-x64': 0.24.0 1194 | dev: true 1195 | 1196 | /escalade@3.2.0: 1197 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 1198 | engines: {node: '>=6'} 1199 | dev: true 1200 | 1201 | /event-target-shim@6.0.2: 1202 | resolution: {integrity: sha512-8q3LsZjRezbFZ2PN+uP+Q7pnHUMmAOziU2vA2OwoFaKIXxlxl38IylhSSgUorWu/rf4er67w0ikBqjBFk/pomA==} 1203 | engines: {node: '>=10.13.0'} 1204 | dev: false 1205 | 1206 | /fast-glob@3.3.2: 1207 | resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} 1208 | engines: {node: '>=8.6.0'} 1209 | dependencies: 1210 | '@nodelib/fs.stat': 2.0.5 1211 | '@nodelib/fs.walk': 1.2.8 1212 | glob-parent: 5.1.2 1213 | merge2: 1.4.1 1214 | micromatch: 4.0.8 1215 | dev: true 1216 | 1217 | /fast-safe-stringify@2.1.1: 1218 | resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} 1219 | dev: false 1220 | 1221 | /fastq@1.17.1: 1222 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 1223 | dependencies: 1224 | reusify: 1.0.4 1225 | dev: true 1226 | 1227 | /fill-range@7.1.1: 1228 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 1229 | engines: {node: '>=8'} 1230 | dependencies: 1231 | to-regex-range: 5.0.1 1232 | dev: true 1233 | 1234 | /flat@6.0.1: 1235 | resolution: {integrity: sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==} 1236 | engines: {node: '>=18'} 1237 | hasBin: true 1238 | dev: false 1239 | 1240 | /foreground-child@3.3.0: 1241 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} 1242 | engines: {node: '>=14'} 1243 | dependencies: 1244 | cross-spawn: 7.0.6 1245 | signal-exit: 4.1.0 1246 | dev: true 1247 | 1248 | /fraction.js@4.3.7: 1249 | resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} 1250 | dev: true 1251 | 1252 | /fsevents@2.3.3: 1253 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1254 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1255 | os: [darwin] 1256 | requiresBuild: true 1257 | dev: true 1258 | optional: true 1259 | 1260 | /function-bind@1.1.2: 1261 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 1262 | dev: true 1263 | 1264 | /gensync@1.0.0-beta.2: 1265 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 1266 | engines: {node: '>=6.9.0'} 1267 | dev: true 1268 | 1269 | /glob-parent@5.1.2: 1270 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1271 | engines: {node: '>= 6'} 1272 | dependencies: 1273 | is-glob: 4.0.3 1274 | dev: true 1275 | 1276 | /glob-parent@6.0.2: 1277 | resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 1278 | engines: {node: '>=10.13.0'} 1279 | dependencies: 1280 | is-glob: 4.0.3 1281 | dev: true 1282 | 1283 | /glob@10.4.5: 1284 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 1285 | hasBin: true 1286 | dependencies: 1287 | foreground-child: 3.3.0 1288 | jackspeak: 3.4.3 1289 | minimatch: 9.0.5 1290 | minipass: 7.1.2 1291 | package-json-from-dist: 1.0.1 1292 | path-scurry: 1.11.1 1293 | dev: true 1294 | 1295 | /globals@11.12.0: 1296 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 1297 | engines: {node: '>=4'} 1298 | dev: true 1299 | 1300 | /globals@15.13.0: 1301 | resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} 1302 | engines: {node: '>=18'} 1303 | dev: true 1304 | 1305 | /goober@2.1.16(csstype@3.1.3): 1306 | resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} 1307 | peerDependencies: 1308 | csstype: ^3.0.10 1309 | dependencies: 1310 | csstype: 3.1.3 1311 | dev: false 1312 | 1313 | /graphql-request@7.1.2(graphql@16.9.0): 1314 | resolution: {integrity: sha512-+XE3iuC55C2di5ZUrB4pjgwe+nIQBuXVIK9J98wrVwojzDW3GMdSBZfxUk8l4j9TieIpjpggclxhNEU9ebGF8w==} 1315 | peerDependencies: 1316 | graphql: 14 - 16 1317 | dependencies: 1318 | '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) 1319 | graphql: 16.9.0 1320 | dev: false 1321 | 1322 | /graphql@16.9.0: 1323 | resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} 1324 | engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} 1325 | dev: false 1326 | 1327 | /hasown@2.0.2: 1328 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 1329 | engines: {node: '>= 0.4'} 1330 | dependencies: 1331 | function-bind: 1.1.2 1332 | dev: true 1333 | 1334 | /is-binary-path@2.1.0: 1335 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 1336 | engines: {node: '>=8'} 1337 | dependencies: 1338 | binary-extensions: 2.3.0 1339 | dev: true 1340 | 1341 | /is-core-module@2.15.1: 1342 | resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 1343 | engines: {node: '>= 0.4'} 1344 | dependencies: 1345 | hasown: 2.0.2 1346 | dev: true 1347 | 1348 | /is-extglob@2.1.1: 1349 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1350 | engines: {node: '>=0.10.0'} 1351 | dev: true 1352 | 1353 | /is-fullwidth-code-point@3.0.0: 1354 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1355 | engines: {node: '>=8'} 1356 | dev: true 1357 | 1358 | /is-glob@4.0.3: 1359 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1360 | engines: {node: '>=0.10.0'} 1361 | dependencies: 1362 | is-extglob: 2.1.1 1363 | dev: true 1364 | 1365 | /is-number@7.0.0: 1366 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1367 | engines: {node: '>=0.12.0'} 1368 | dev: true 1369 | 1370 | /is-plain-object@2.0.4: 1371 | resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} 1372 | engines: {node: '>=0.10.0'} 1373 | dependencies: 1374 | isobject: 3.0.1 1375 | dev: false 1376 | 1377 | /is-primitive@3.0.1: 1378 | resolution: {integrity: sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w==} 1379 | engines: {node: '>=0.10.0'} 1380 | dev: false 1381 | 1382 | /is-what@4.1.16: 1383 | resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} 1384 | engines: {node: '>=12.13'} 1385 | dev: false 1386 | 1387 | /isexe@2.0.0: 1388 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1389 | dev: true 1390 | 1391 | /isobject@3.0.1: 1392 | resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} 1393 | engines: {node: '>=0.10.0'} 1394 | dev: false 1395 | 1396 | /isomorphic-ws@5.0.0(ws@8.18.0): 1397 | resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} 1398 | peerDependencies: 1399 | ws: '*' 1400 | dependencies: 1401 | ws: 8.18.0 1402 | dev: false 1403 | 1404 | /jackspeak@3.4.3: 1405 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 1406 | dependencies: 1407 | '@isaacs/cliui': 8.0.2 1408 | optionalDependencies: 1409 | '@pkgjs/parseargs': 0.11.0 1410 | dev: true 1411 | 1412 | /jiti@1.21.6: 1413 | resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} 1414 | hasBin: true 1415 | dev: true 1416 | 1417 | /js-tokens@4.0.0: 1418 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1419 | 1420 | /jsesc@3.1.0: 1421 | resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} 1422 | engines: {node: '>=6'} 1423 | hasBin: true 1424 | dev: true 1425 | 1426 | /json5@2.2.3: 1427 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 1428 | engines: {node: '>=6'} 1429 | hasBin: true 1430 | dev: true 1431 | 1432 | /lilconfig@3.1.3: 1433 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} 1434 | engines: {node: '>=14'} 1435 | dev: true 1436 | 1437 | /lines-and-columns@1.2.4: 1438 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 1439 | dev: true 1440 | 1441 | /loose-envify@1.4.0: 1442 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 1443 | hasBin: true 1444 | dependencies: 1445 | js-tokens: 4.0.0 1446 | dev: false 1447 | 1448 | /lru-cache@10.4.3: 1449 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 1450 | dev: true 1451 | 1452 | /lru-cache@5.1.1: 1453 | resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} 1454 | dependencies: 1455 | yallist: 3.1.1 1456 | dev: true 1457 | 1458 | /merge2@1.4.1: 1459 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1460 | engines: {node: '>= 8'} 1461 | dev: true 1462 | 1463 | /micromatch@4.0.8: 1464 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1465 | engines: {node: '>=8.6'} 1466 | dependencies: 1467 | braces: 3.0.3 1468 | picomatch: 2.3.1 1469 | dev: true 1470 | 1471 | /minimatch@9.0.5: 1472 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1473 | engines: {node: '>=16 || 14 >=14.17'} 1474 | dependencies: 1475 | brace-expansion: 2.0.1 1476 | dev: true 1477 | 1478 | /minipass@7.1.2: 1479 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1480 | engines: {node: '>=16 || 14 >=14.17'} 1481 | dev: true 1482 | 1483 | /ms@2.1.3: 1484 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1485 | dev: true 1486 | 1487 | /mutative@1.1.0: 1488 | resolution: {integrity: sha512-2PJADREjOusk3iJkD3rXV2YjAxTuaLxdfqtqTEt6vcY07LtEBR1seHuBHXWEIuscqRDGvbauYPs+A4Rj/KTczQ==} 1489 | engines: {node: '>=14.0'} 1490 | dev: false 1491 | 1492 | /mz@2.7.0: 1493 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 1494 | dependencies: 1495 | any-promise: 1.3.0 1496 | object-assign: 4.1.1 1497 | thenify-all: 1.6.0 1498 | dev: true 1499 | 1500 | /nanoid@3.3.8: 1501 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} 1502 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1503 | hasBin: true 1504 | dev: true 1505 | 1506 | /node-releases@2.0.19: 1507 | resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} 1508 | dev: true 1509 | 1510 | /normalize-path@3.0.0: 1511 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1512 | engines: {node: '>=0.10.0'} 1513 | dev: true 1514 | 1515 | /normalize-range@0.1.2: 1516 | resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} 1517 | engines: {node: '>=0.10.0'} 1518 | dev: true 1519 | 1520 | /object-assign@4.1.1: 1521 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1522 | engines: {node: '>=0.10.0'} 1523 | 1524 | /object-hash@3.0.0: 1525 | resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} 1526 | engines: {node: '>= 6'} 1527 | dev: true 1528 | 1529 | /package-json-from-dist@1.0.1: 1530 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1531 | dev: true 1532 | 1533 | /partysocket@0.0.25: 1534 | resolution: {integrity: sha512-1oCGA65fydX/FgdnsiBh68buOvfxuteoZVSb3Paci2kRp/7lhF0HyA8EDb5X/O6FxId1e+usPTQNRuzFEvkJbQ==} 1535 | dependencies: 1536 | event-target-shim: 6.0.2 1537 | dev: false 1538 | 1539 | /path-key@3.1.1: 1540 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1541 | engines: {node: '>=8'} 1542 | dev: true 1543 | 1544 | /path-parse@1.0.7: 1545 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1546 | dev: true 1547 | 1548 | /path-scurry@1.11.1: 1549 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1550 | engines: {node: '>=16 || 14 >=14.18'} 1551 | dependencies: 1552 | lru-cache: 10.4.3 1553 | minipass: 7.1.2 1554 | dev: true 1555 | 1556 | /picocolors@1.1.1: 1557 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1558 | dev: true 1559 | 1560 | /picomatch@2.3.1: 1561 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1562 | engines: {node: '>=8.6'} 1563 | dev: true 1564 | 1565 | /pify@2.3.0: 1566 | resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} 1567 | engines: {node: '>=0.10.0'} 1568 | dev: true 1569 | 1570 | /pirates@4.0.6: 1571 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} 1572 | engines: {node: '>= 6'} 1573 | dev: true 1574 | 1575 | /postcss-import@15.1.0(postcss@8.4.49): 1576 | resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} 1577 | engines: {node: '>=14.0.0'} 1578 | peerDependencies: 1579 | postcss: ^8.0.0 1580 | dependencies: 1581 | postcss: 8.4.49 1582 | postcss-value-parser: 4.2.0 1583 | read-cache: 1.0.0 1584 | resolve: 1.22.8 1585 | dev: true 1586 | 1587 | /postcss-js@4.0.1(postcss@8.4.49): 1588 | resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} 1589 | engines: {node: ^12 || ^14 || >= 16} 1590 | peerDependencies: 1591 | postcss: ^8.4.21 1592 | dependencies: 1593 | camelcase-css: 2.0.1 1594 | postcss: 8.4.49 1595 | dev: true 1596 | 1597 | /postcss-load-config@4.0.2(postcss@8.4.49): 1598 | resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} 1599 | engines: {node: '>= 14'} 1600 | peerDependencies: 1601 | postcss: '>=8.0.9' 1602 | ts-node: '>=9.0.0' 1603 | peerDependenciesMeta: 1604 | postcss: 1605 | optional: true 1606 | ts-node: 1607 | optional: true 1608 | dependencies: 1609 | lilconfig: 3.1.3 1610 | postcss: 8.4.49 1611 | yaml: 2.6.1 1612 | dev: true 1613 | 1614 | /postcss-nested@6.2.0(postcss@8.4.49): 1615 | resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} 1616 | engines: {node: '>=12.0'} 1617 | peerDependencies: 1618 | postcss: ^8.2.14 1619 | dependencies: 1620 | postcss: 8.4.49 1621 | postcss-selector-parser: 6.1.2 1622 | dev: true 1623 | 1624 | /postcss-selector-parser@6.1.2: 1625 | resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} 1626 | engines: {node: '>=4'} 1627 | dependencies: 1628 | cssesc: 3.0.0 1629 | util-deprecate: 1.0.2 1630 | dev: true 1631 | 1632 | /postcss-value-parser@4.2.0: 1633 | resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 1634 | dev: true 1635 | 1636 | /postcss@8.4.49: 1637 | resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} 1638 | engines: {node: ^10 || ^12 || >=14} 1639 | dependencies: 1640 | nanoid: 3.3.8 1641 | picocolors: 1.1.1 1642 | source-map-js: 1.2.1 1643 | dev: true 1644 | 1645 | /prop-types@15.8.1: 1646 | resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} 1647 | dependencies: 1648 | loose-envify: 1.4.0 1649 | object-assign: 4.1.1 1650 | react-is: 16.13.1 1651 | dev: false 1652 | 1653 | /queue-microtask@1.2.3: 1654 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1655 | dev: true 1656 | 1657 | /react-dom@18.3.1(react@18.3.1): 1658 | resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} 1659 | peerDependencies: 1660 | react: ^18.3.1 1661 | dependencies: 1662 | loose-envify: 1.4.0 1663 | react: 18.3.1 1664 | scheduler: 0.23.2 1665 | dev: false 1666 | 1667 | /react-fast-compare@3.2.2: 1668 | resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} 1669 | dev: false 1670 | 1671 | /react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.3.1)(react@18.3.1): 1672 | resolution: {integrity: sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==} 1673 | engines: {node: '>=10'} 1674 | peerDependencies: 1675 | react: '>=16' 1676 | react-dom: '>=16' 1677 | dependencies: 1678 | goober: 2.1.16(csstype@3.1.3) 1679 | react: 18.3.1 1680 | react-dom: 18.3.1(react@18.3.1) 1681 | transitivePeerDependencies: 1682 | - csstype 1683 | dev: false 1684 | 1685 | /react-infinite-scroll-hook@5.0.1(react-dom@18.3.1)(react@18.3.1): 1686 | resolution: {integrity: sha512-fn6+8BAZLQ9C1fvO5kPicGjDR2WHxK7rP4aaSWuaJkvtoJjYuudGJ9wjgPox7dghKm5Xj9cpKFycM86/wAJ3ig==} 1687 | peerDependencies: 1688 | react: '>=16.8.0' 1689 | react-dom: '>=16.8.0' 1690 | dependencies: 1691 | react: 18.3.1 1692 | react-dom: 18.3.1(react@18.3.1) 1693 | react-intersection-observer-hook: 3.0.1(react-dom@18.3.1)(react@18.3.1) 1694 | dev: false 1695 | 1696 | /react-intersection-observer-hook@3.0.1(react-dom@18.3.1)(react@18.3.1): 1697 | resolution: {integrity: sha512-nehzFUV+jVY49tc9FOm4yJHrmFFtCmsBZKiN1rUUB2675CMBf6kKu1ekuTqvCnmh4XG7RFP3bMyAevfqfV94xw==} 1698 | peerDependencies: 1699 | react: '>=16.8.0' 1700 | react-dom: '>=16.8.0' 1701 | dependencies: 1702 | react: 18.3.1 1703 | react-dom: 18.3.1(react@18.3.1) 1704 | dev: false 1705 | 1706 | /react-is@16.13.1: 1707 | resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} 1708 | dev: false 1709 | 1710 | /react-refresh@0.14.2: 1711 | resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} 1712 | engines: {node: '>=0.10.0'} 1713 | dev: true 1714 | 1715 | /react-transition-group@4.4.5(react-dom@18.3.1)(react@18.3.1): 1716 | resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} 1717 | peerDependencies: 1718 | react: '>=16.6.0' 1719 | react-dom: '>=16.6.0' 1720 | dependencies: 1721 | '@babel/runtime': 7.26.0 1722 | dom-helpers: 5.2.1 1723 | loose-envify: 1.4.0 1724 | prop-types: 15.8.1 1725 | react: 18.3.1 1726 | react-dom: 18.3.1(react@18.3.1) 1727 | dev: false 1728 | 1729 | /react@18.3.1: 1730 | resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} 1731 | engines: {node: '>=0.10.0'} 1732 | dependencies: 1733 | loose-envify: 1.4.0 1734 | dev: false 1735 | 1736 | /read-cache@1.0.0: 1737 | resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} 1738 | dependencies: 1739 | pify: 2.3.0 1740 | dev: true 1741 | 1742 | /readdirp@3.6.0: 1743 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1744 | engines: {node: '>=8.10.0'} 1745 | dependencies: 1746 | picomatch: 2.3.1 1747 | dev: true 1748 | 1749 | /regenerator-runtime@0.14.1: 1750 | resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} 1751 | dev: false 1752 | 1753 | /remeda@2.17.4: 1754 | resolution: {integrity: sha512-pviU2Ag7Qx9mOCAKO4voxDx/scfLzdhp3v85qDO4xxntQsU76uE9sgrAAdK1ATn4zzaOJqCXYMMNRP+O9F4Wiw==} 1755 | dependencies: 1756 | type-fest: 4.30.1 1757 | dev: false 1758 | 1759 | /resolve@1.22.8: 1760 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 1761 | hasBin: true 1762 | dependencies: 1763 | is-core-module: 2.15.1 1764 | path-parse: 1.0.7 1765 | supports-preserve-symlinks-flag: 1.0.0 1766 | dev: true 1767 | 1768 | /reusify@1.0.4: 1769 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1770 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1771 | dev: true 1772 | 1773 | /rollup@4.28.1: 1774 | resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==} 1775 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1776 | hasBin: true 1777 | dependencies: 1778 | '@types/estree': 1.0.6 1779 | optionalDependencies: 1780 | '@rollup/rollup-android-arm-eabi': 4.28.1 1781 | '@rollup/rollup-android-arm64': 4.28.1 1782 | '@rollup/rollup-darwin-arm64': 4.28.1 1783 | '@rollup/rollup-darwin-x64': 4.28.1 1784 | '@rollup/rollup-freebsd-arm64': 4.28.1 1785 | '@rollup/rollup-freebsd-x64': 4.28.1 1786 | '@rollup/rollup-linux-arm-gnueabihf': 4.28.1 1787 | '@rollup/rollup-linux-arm-musleabihf': 4.28.1 1788 | '@rollup/rollup-linux-arm64-gnu': 4.28.1 1789 | '@rollup/rollup-linux-arm64-musl': 4.28.1 1790 | '@rollup/rollup-linux-loongarch64-gnu': 4.28.1 1791 | '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1 1792 | '@rollup/rollup-linux-riscv64-gnu': 4.28.1 1793 | '@rollup/rollup-linux-s390x-gnu': 4.28.1 1794 | '@rollup/rollup-linux-x64-gnu': 4.28.1 1795 | '@rollup/rollup-linux-x64-musl': 4.28.1 1796 | '@rollup/rollup-win32-arm64-msvc': 4.28.1 1797 | '@rollup/rollup-win32-ia32-msvc': 4.28.1 1798 | '@rollup/rollup-win32-x64-msvc': 4.28.1 1799 | fsevents: 2.3.3 1800 | dev: true 1801 | 1802 | /run-parallel@1.2.0: 1803 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1804 | dependencies: 1805 | queue-microtask: 1.2.3 1806 | dev: true 1807 | 1808 | /safe-stable-stringify@2.5.0: 1809 | resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} 1810 | engines: {node: '>=10'} 1811 | dev: false 1812 | 1813 | /scheduler@0.23.2: 1814 | resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} 1815 | dependencies: 1816 | loose-envify: 1.4.0 1817 | dev: false 1818 | 1819 | /semver@6.3.1: 1820 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1821 | hasBin: true 1822 | dev: true 1823 | 1824 | /set-value@4.1.0: 1825 | resolution: {integrity: sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw==} 1826 | engines: {node: '>=11.0'} 1827 | dependencies: 1828 | is-plain-object: 2.0.4 1829 | is-primitive: 3.0.1 1830 | dev: false 1831 | 1832 | /shebang-command@2.0.0: 1833 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1834 | engines: {node: '>=8'} 1835 | dependencies: 1836 | shebang-regex: 3.0.0 1837 | dev: true 1838 | 1839 | /shebang-regex@3.0.0: 1840 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1841 | engines: {node: '>=8'} 1842 | dev: true 1843 | 1844 | /signal-exit@4.1.0: 1845 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1846 | engines: {node: '>=14'} 1847 | dev: true 1848 | 1849 | /source-map-js@1.2.1: 1850 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1851 | engines: {node: '>=0.10.0'} 1852 | dev: true 1853 | 1854 | /string-width@4.2.3: 1855 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1856 | engines: {node: '>=8'} 1857 | dependencies: 1858 | emoji-regex: 8.0.0 1859 | is-fullwidth-code-point: 3.0.0 1860 | strip-ansi: 6.0.1 1861 | dev: true 1862 | 1863 | /string-width@5.1.2: 1864 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1865 | engines: {node: '>=12'} 1866 | dependencies: 1867 | eastasianwidth: 0.2.0 1868 | emoji-regex: 9.2.2 1869 | strip-ansi: 7.1.0 1870 | dev: true 1871 | 1872 | /strip-ansi@6.0.1: 1873 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1874 | engines: {node: '>=8'} 1875 | dependencies: 1876 | ansi-regex: 5.0.1 1877 | dev: true 1878 | 1879 | /strip-ansi@7.1.0: 1880 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1881 | engines: {node: '>=12'} 1882 | dependencies: 1883 | ansi-regex: 6.1.0 1884 | dev: true 1885 | 1886 | /sucrase@3.35.0: 1887 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1888 | engines: {node: '>=16 || 14 >=14.17'} 1889 | hasBin: true 1890 | dependencies: 1891 | '@jridgewell/gen-mapping': 0.3.8 1892 | commander: 4.1.1 1893 | glob: 10.4.5 1894 | lines-and-columns: 1.2.4 1895 | mz: 2.7.0 1896 | pirates: 4.0.6 1897 | ts-interface-checker: 0.1.13 1898 | dev: true 1899 | 1900 | /superjson@1.13.3: 1901 | resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==} 1902 | engines: {node: '>=10'} 1903 | dependencies: 1904 | copy-anything: 3.0.5 1905 | dev: false 1906 | 1907 | /supports-preserve-symlinks-flag@1.0.0: 1908 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1909 | engines: {node: '>= 0.4'} 1910 | dev: true 1911 | 1912 | /tailwindcss@3.4.16: 1913 | resolution: {integrity: sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==} 1914 | engines: {node: '>=14.0.0'} 1915 | hasBin: true 1916 | dependencies: 1917 | '@alloc/quick-lru': 5.2.0 1918 | arg: 5.0.2 1919 | chokidar: 3.6.0 1920 | didyoumean: 1.2.2 1921 | dlv: 1.1.3 1922 | fast-glob: 3.3.2 1923 | glob-parent: 6.0.2 1924 | is-glob: 4.0.3 1925 | jiti: 1.21.6 1926 | lilconfig: 3.1.3 1927 | micromatch: 4.0.8 1928 | normalize-path: 3.0.0 1929 | object-hash: 3.0.0 1930 | picocolors: 1.1.1 1931 | postcss: 8.4.49 1932 | postcss-import: 15.1.0(postcss@8.4.49) 1933 | postcss-js: 4.0.1(postcss@8.4.49) 1934 | postcss-load-config: 4.0.2(postcss@8.4.49) 1935 | postcss-nested: 6.2.0(postcss@8.4.49) 1936 | postcss-selector-parser: 6.1.2 1937 | resolve: 1.22.8 1938 | sucrase: 3.35.0 1939 | transitivePeerDependencies: 1940 | - ts-node 1941 | dev: true 1942 | 1943 | /thenify-all@1.6.0: 1944 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1945 | engines: {node: '>=0.8'} 1946 | dependencies: 1947 | thenify: 3.3.1 1948 | dev: true 1949 | 1950 | /thenify@3.3.1: 1951 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1952 | dependencies: 1953 | any-promise: 1.3.0 1954 | dev: true 1955 | 1956 | /to-regex-range@5.0.1: 1957 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1958 | engines: {node: '>=8.0'} 1959 | dependencies: 1960 | is-number: 7.0.0 1961 | dev: true 1962 | 1963 | /ts-interface-checker@0.1.13: 1964 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1965 | dev: true 1966 | 1967 | /type-fest@4.30.1: 1968 | resolution: {integrity: sha512-ojFL7eDMX2NF0xMbDwPZJ8sb7ckqtlAi1GsmgsFXvErT9kFTk1r0DuQKvrCh73M6D4nngeHJmvogF9OluXs7Hw==} 1969 | engines: {node: '>=16'} 1970 | dev: false 1971 | 1972 | /typescript@5.6.3: 1973 | resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} 1974 | engines: {node: '>=14.17'} 1975 | hasBin: true 1976 | dev: true 1977 | 1978 | /update-browserslist-db@1.1.1(browserslist@4.24.2): 1979 | resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} 1980 | hasBin: true 1981 | peerDependencies: 1982 | browserslist: '>= 4.21.0' 1983 | dependencies: 1984 | browserslist: 4.24.2 1985 | escalade: 3.2.0 1986 | picocolors: 1.1.1 1987 | dev: true 1988 | 1989 | /use-isomorphic-layout-effect@1.2.0(@types/react@18.3.16)(react@18.3.1): 1990 | resolution: {integrity: sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w==} 1991 | peerDependencies: 1992 | '@types/react': '*' 1993 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 1994 | peerDependenciesMeta: 1995 | '@types/react': 1996 | optional: true 1997 | dependencies: 1998 | '@types/react': 18.3.16 1999 | react: 18.3.1 2000 | dev: false 2001 | 2002 | /use-sync-external-store@1.4.0(react@18.3.1): 2003 | resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} 2004 | peerDependencies: 2005 | react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 2006 | dependencies: 2007 | react: 18.3.1 2008 | dev: false 2009 | 2010 | /util-deprecate@1.0.2: 2011 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 2012 | dev: true 2013 | 2014 | /uuid@9.0.1: 2015 | resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} 2016 | hasBin: true 2017 | dev: false 2018 | 2019 | /vite@6.0.3: 2020 | resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==} 2021 | engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 2022 | hasBin: true 2023 | peerDependencies: 2024 | '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 2025 | jiti: '>=1.21.0' 2026 | less: '*' 2027 | lightningcss: ^1.21.0 2028 | sass: '*' 2029 | sass-embedded: '*' 2030 | stylus: '*' 2031 | sugarss: '*' 2032 | terser: ^5.16.0 2033 | tsx: ^4.8.1 2034 | yaml: ^2.4.2 2035 | peerDependenciesMeta: 2036 | '@types/node': 2037 | optional: true 2038 | jiti: 2039 | optional: true 2040 | less: 2041 | optional: true 2042 | lightningcss: 2043 | optional: true 2044 | sass: 2045 | optional: true 2046 | sass-embedded: 2047 | optional: true 2048 | stylus: 2049 | optional: true 2050 | sugarss: 2051 | optional: true 2052 | terser: 2053 | optional: true 2054 | tsx: 2055 | optional: true 2056 | yaml: 2057 | optional: true 2058 | dependencies: 2059 | esbuild: 0.24.0 2060 | postcss: 8.4.49 2061 | rollup: 4.28.1 2062 | optionalDependencies: 2063 | fsevents: 2.3.3 2064 | dev: true 2065 | 2066 | /which@2.0.2: 2067 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 2068 | engines: {node: '>= 8'} 2069 | hasBin: true 2070 | dependencies: 2071 | isexe: 2.0.0 2072 | dev: true 2073 | 2074 | /wrap-ansi@7.0.0: 2075 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 2076 | engines: {node: '>=10'} 2077 | dependencies: 2078 | ansi-styles: 4.3.0 2079 | string-width: 4.2.3 2080 | strip-ansi: 6.0.1 2081 | dev: true 2082 | 2083 | /wrap-ansi@8.1.0: 2084 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 2085 | engines: {node: '>=12'} 2086 | dependencies: 2087 | ansi-styles: 6.2.1 2088 | string-width: 5.1.2 2089 | strip-ansi: 7.1.0 2090 | dev: true 2091 | 2092 | /ws@8.18.0: 2093 | resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} 2094 | engines: {node: '>=10.0.0'} 2095 | peerDependencies: 2096 | bufferutil: ^4.0.1 2097 | utf-8-validate: '>=5.0.2' 2098 | peerDependenciesMeta: 2099 | bufferutil: 2100 | optional: true 2101 | utf-8-validate: 2102 | optional: true 2103 | dev: false 2104 | 2105 | /xstate@5.18.2: 2106 | resolution: {integrity: sha512-hab5VOe29D0agy8/7dH1lGw+7kilRQyXwpaChoMu4fe6rDP+nsHYhDYKfS2O4iXE7myA98TW6qMEudj/8NXEkA==} 2107 | dev: false 2108 | 2109 | /yallist@3.1.1: 2110 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 2111 | dev: true 2112 | 2113 | /yaml@2.6.1: 2114 | resolution: {integrity: sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==} 2115 | engines: {node: '>= 14'} 2116 | hasBin: true 2117 | dev: true 2118 | 2119 | /zod@3.23.8: 2120 | resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} 2121 | dev: false 2122 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | } 6 | } -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { Frame } from "@shopify/polaris" 2 | 3 | import { Notifications } from "./components/Notifications.tsx" 4 | import { AppExampleSandbox } from "./machines/inspector/inspector.machine.tsx" 5 | import { Root } from "./machines/root/root.view.tsx" 6 | import { PolarisProvider } from "./providers/polaris.provider" 7 | 8 | function App() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | 19 | export default App 20 | -------------------------------------------------------------------------------- /src/assets/usage-stately-actors.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djang0dev/special-shopify-resource-picker/9939766d06f071eb9bac20c11920be12b4b3a6f9/src/assets/usage-stately-actors.mp4 -------------------------------------------------------------------------------- /src/commons/entities.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | 3 | export const PageInfo = z.object({ 4 | hasNextPage: z.boolean(), 5 | hasPreviousPage: z.boolean(), 6 | startCursor: z.string().optional().nullable(), 7 | endCursor: z.string().optional().nullable(), 8 | }) 9 | 10 | export type PageInfo = z.infer 11 | 12 | export interface Product { 13 | id: string 14 | title: string 15 | description: string 16 | featuredImage: { 17 | id: string 18 | url: string 19 | } 20 | variants: { 21 | edges: { 22 | node: { 23 | price: { 24 | amount: string 25 | currencyCode: string 26 | } 27 | } 28 | }[] 29 | } 30 | } 31 | 32 | export interface ProductsResponse { 33 | products: { 34 | pageInfo: PageInfo 35 | edges: { 36 | node: Product 37 | }[] 38 | } 39 | } 40 | 41 | interface CollectionImage { 42 | url: string 43 | } 44 | 45 | interface CollectionNode { 46 | id: string 47 | title: string 48 | description: string 49 | image: CollectionImage 50 | } 51 | 52 | interface CollectionEdge { 53 | node: CollectionNode 54 | } 55 | 56 | export interface CollectionQueryResponse { 57 | collections: { 58 | pageInfo: PageInfo 59 | edges: CollectionEdge[] 60 | } 61 | } 62 | 63 | export interface CollectionQueryVariables { 64 | first: number 65 | after?: string 66 | query?: string 67 | } 68 | 69 | export const zDate = z.union([z.string(), z.date()]).pipe(z.coerce.date()) 70 | // Basic app local handled for now 71 | export const AppLocales = z.object({ 72 | "en-US": z.string(), 73 | }) 74 | export type AppLocales = z.infer 75 | 76 | // Related to resource picker 77 | export const LibraryQuery = z.object({ 78 | query: z.string().nullable(), 79 | filters: z.object({ 80 | tags: z.array(z.string()).nullable().default(null), 81 | }), 82 | // query: z.string(), 83 | endCursor: z 84 | .string() 85 | .nullable() 86 | .optional() 87 | .default(null) 88 | .transform((v) => v ?? null), 89 | first: z 90 | .string() 91 | .or(z.number()) 92 | .optional() 93 | .default(10) 94 | .transform((v) => Number.parseInt(String(v))), 95 | }) 96 | export type LibraryQuery = z.infer 97 | 98 | export const BaseResource = z.object({ 99 | id: z.string(), 100 | mainImageSrc: z.string().nullable(), 101 | }) 102 | 103 | export const LibraryStaticImage = z.object({ 104 | resourceType: z.literal("libraryStaticImage"), 105 | data: z.object({ 106 | src: z.string(), 107 | }), 108 | }) 109 | 110 | export const LibraryResourceFilters = z.object({ 111 | filters: z.object({ 112 | tags: z.array(z.string()), 113 | }), 114 | }) 115 | 116 | export type LibraryResourceFilters = z.infer 117 | 118 | export const LibraryResource = BaseResource.extend({ 119 | title: AppLocales, 120 | resourceNamespace: z.literal("library"), 121 | description: AppLocales.nullable(), 122 | tags: z.array(z.string()).nullable(), 123 | allowedPlanSlugs: z.array(z.union([z.string(), z.literal("all")])), 124 | status: z.enum(["active", "draft"]), 125 | resource: z.discriminatedUnion("resourceType", [LibraryStaticImage]), 126 | createdAt: zDate, 127 | updatedAt: zDate, 128 | cursor: z.number(), 129 | }) 130 | export type LibraryResourceTypeUnion = LibraryResource["resource"]["resourceType"] 131 | 132 | // export const LibraryResourceType = z.enum([ 133 | // LibrarySizeChart.shape.resourceType.value, 134 | // LibraryStaticImage.shape.resourceType.value, 135 | // ]) 136 | 137 | export const ShopifyResource = BaseResource.extend({ 138 | resourceNamespace: z.literal("shopify"), 139 | // FIXME: redundancy with title title here and inside resource, this is shit 140 | title: z.string(), 141 | resource: z.discriminatedUnion("resourceType", [ 142 | z.object({ resourceType: z.literal("product"), title: z.string() }), 143 | z.object({ resourceType: z.literal("collection"), title: z.string() }), 144 | ]), 145 | }) 146 | 147 | export type ShopifyResource = z.infer 148 | 149 | export type ShopifyResourceTypeUnion = ShopifyResource["resource"]["resourceType"] 150 | 151 | export type LibraryResource = z.infer 152 | 153 | // Extract doesn't work like this Extract = 155 | LibraryResource extends { resource: infer R } 156 | ? R extends { resourceType: TResourceType } 157 | ? Omit & { resource: R } 158 | : never 159 | : never 160 | 161 | export const ShopifyQuery = z.object({ 162 | query: z.string(), 163 | endCursor: z 164 | .string() 165 | .nullable() 166 | .optional() 167 | .default(null) 168 | .transform((v) => v ?? null), 169 | first: z 170 | .string() 171 | .or(z.number()) 172 | .optional() 173 | .default(10) 174 | .transform((v) => Number.parseInt(String(v))), 175 | }) 176 | 177 | export type ShopifyQuery = z.infer 178 | export type LibraryStaticImage = GetLibraryResource<"libraryStaticImage"> 179 | 180 | export const Resource = z.discriminatedUnion("resourceNamespace", [ 181 | LibraryResource, 182 | ShopifyResource, 183 | ]) 184 | export type Resource = z.infer 185 | 186 | export type ResourceNamespace = Resource["resourceNamespace"] 187 | export type ResourceType = Resource["resource"]["resourceType"] 188 | -------------------------------------------------------------------------------- /src/commons/http-errors.ts: -------------------------------------------------------------------------------- 1 | import toast from "react-hot-toast/headless" 2 | import type { ErrorActorEvent } from "xstate" 3 | 4 | export type HttpStatus = 5 | | 100 6 | | 101 7 | | 102 8 | | 103 9 | | 200 10 | | 201 11 | | 202 12 | | 203 13 | | 204 14 | | 205 15 | | 206 16 | | 207 17 | | 208 18 | | 226 19 | | 300 20 | | 301 21 | | 302 22 | | 303 23 | | 304 24 | | 305 25 | | 306 26 | | 307 27 | | 308 28 | | 400 29 | | 401 30 | | 402 31 | | 403 32 | | 404 33 | | 405 34 | | 406 35 | | 407 36 | | 408 37 | | 409 38 | | 410 39 | | 411 40 | | 412 41 | | 413 42 | | 414 43 | | 415 44 | | 416 45 | | 417 46 | | 418 47 | | 419 48 | | 421 49 | | 422 50 | | 423 51 | | 424 52 | | 425 53 | | 426 54 | | 428 55 | | 429 56 | | 431 57 | | 451 58 | | 500 59 | | 501 60 | | 502 61 | | 503 62 | | 504 63 | | 505 64 | | 506 65 | | 507 66 | | 508 67 | | 510 68 | | 511 69 | 70 | export interface AppHttpExceptionPayload { 71 | type?: TExceptionTypes 72 | code?: TExceptionCodes 73 | status?: number 74 | isOperational?: boolean 75 | message: string 76 | errorDetails?: { key: string; value: string }[] 77 | additionalInfo?: Record 78 | rawError: Error 79 | stackTrace?: string 80 | } 81 | export type AppHttpExceptionClientPayload = Omit< 82 | AppHttpExceptionPayload, 83 | "rawError" | "stack" 84 | > 85 | 86 | export interface SerializedHttpErrorClient { 87 | http: { 88 | method: string 89 | status: HttpStatus 90 | requestId: string 91 | path: string 92 | } 93 | error: AppHttpExceptionClientPayload 94 | metas: { 95 | dateISOString: string 96 | timestamp: number 97 | } 98 | } 99 | 100 | const isASerializedHttpErrorClient = (error: unknown): error is SerializedHttpErrorClient => 101 | typeof error === "object" && 102 | error !== null && 103 | "http" in error && 104 | "error" in error && 105 | "metas" in error 106 | export const handleInvokeError = ({ event }: { event: ErrorActorEvent }): void => { 107 | console.error(event.error) 108 | const error = event.error ?? {} 109 | if (isASerializedHttpErrorClient(error)) { 110 | // @ts-expect-error TODO: Fix because not sure about error handling with client side error (not from the api) 111 | toast.error(error, { style: { maxHeight: "150px" } }) 112 | return 113 | } 114 | toast.error(Reflect.get(error, "message") ?? "Something went wrong, please contact support.") 115 | } 116 | -------------------------------------------------------------------------------- /src/components/Notifications.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unnecessary-condition */ 2 | 3 | import { Toast } from "@shopify/polaris" 4 | import toast, { useToaster } from "react-hot-toast/headless" 5 | import { handleErrorMessage } from "../utils" 6 | 7 | export const Notifications = () => { 8 | const { toasts, handlers } = useToaster() 9 | const { startPause, endPause } = handlers 10 | return ( 11 |
12 | {toasts 13 | .filter((t) => t.visible) 14 | .map((t) => { 15 | if (!t) return null 16 | if (t.type === "error") { 17 | const errorMessage = handleErrorMessage(t.message) 18 | return ( 19 |
20 | 26 | 27 | {errorMessage} 28 | 29 |
30 | } 31 | onDismiss={() => { 32 | toast.dismiss(t.id) 33 | }} 34 | /> 35 |
36 | ) 37 | } 38 | return ( 39 |
40 | { 44 | toast.dismiss(t.id) 45 | }} 46 | /> 47 |
48 | ) 49 | })} 50 | 51 | ) 52 | } 53 | -------------------------------------------------------------------------------- /src/data/library-static-images-resources.data.ts: -------------------------------------------------------------------------------- 1 | import { LibraryStaticImage } from "../commons/entities.ts" 2 | import { getPaginatedLibraryResources } from "../utils.ts" 3 | 4 | export const libraryStaticImageResources = [ 5 | { 6 | id: "ff21133c-c65c-4261-89c7-5cc11a068c10", 7 | cursor: 270, 8 | tags: ["bags", "no-arrows"], 9 | allowedPlanSlugs: ["all"], 10 | title: { "en-US": "Shopping Bag" }, 11 | description: null, 12 | mainImageSrc: 13 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset137-na_bAHLww.svg?v=1717077352", 14 | status: "active", 15 | createdAt: new Date("2024-06-08 11:21:30.928078 +00:00"), 16 | updatedAt: new Date("2024-06-08 11:21:30.928078 +00:00"), 17 | resource: { 18 | resourceType: "libraryStaticImage", 19 | data: { 20 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset137-na_bAHLww.svg?v=1717077352", 21 | }, 22 | }, 23 | resourceNamespace: "library", 24 | }, 25 | { 26 | id: "b5634ac2-772a-4373-841e-8d67537993cd", 27 | cursor: 271, 28 | tags: ["bags", "arrows"], 29 | allowedPlanSlugs: ["all"], 30 | title: { "en-US": "Shopping Bag" }, 31 | description: null, 32 | mainImageSrc: 33 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset137_bAHLww.svg?v=1717077352", 34 | status: "active", 35 | createdAt: new Date("2024-06-08 11:21:30.928078 +00:00"), 36 | updatedAt: new Date("2024-06-08 11:21:30.928078 +00:00"), 37 | resource: { 38 | resourceType: "libraryStaticImage", 39 | data: { 40 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset137_bAHLww.svg?v=1717077352", 41 | }, 42 | }, 43 | resourceNamespace: "library", 44 | }, 45 | { 46 | id: "db745256-9dfc-4212-b85a-82574c6e4915", 47 | cursor: 272, 48 | tags: ["bags", "no-arrows"], 49 | allowedPlanSlugs: ["all"], 50 | title: { "en-US": "Messenger Bag" }, 51 | description: null, 52 | mainImageSrc: 53 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset138-na_VuTFud.svg?v=1717077352", 54 | status: "active", 55 | createdAt: new Date("2024-06-08 11:23:11.742576 +00:00"), 56 | updatedAt: new Date("2024-06-08 11:23:11.742576 +00:00"), 57 | resource: { 58 | resourceType: "libraryStaticImage", 59 | data: { 60 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset138-na_VuTFud.svg?v=1717077352", 61 | }, 62 | }, 63 | resourceNamespace: "library", 64 | }, 65 | { 66 | id: "ad7cd813-52ea-4850-9725-af96dae2707d", 67 | cursor: 273, 68 | tags: ["bags", "arrows"], 69 | allowedPlanSlugs: ["all"], 70 | title: { "en-US": "Messenger Bag" }, 71 | description: null, 72 | mainImageSrc: 73 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset138_VuTFud.svg?v=1717077352", 74 | status: "active", 75 | createdAt: new Date("2024-06-08 11:23:11.742576 +00:00"), 76 | updatedAt: new Date("2024-06-08 11:23:11.742576 +00:00"), 77 | resource: { 78 | resourceType: "libraryStaticImage", 79 | data: { 80 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset138_VuTFud.svg?v=1717077352", 81 | }, 82 | }, 83 | resourceNamespace: "library", 84 | }, 85 | { 86 | id: "84ef61fd-5d32-4b41-a641-0e15fec736e8", 87 | cursor: 274, 88 | tags: ["bags", "no-arrows"], 89 | allowedPlanSlugs: ["all"], 90 | title: { "en-US": "Crescent Bag" }, 91 | description: null, 92 | mainImageSrc: 93 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset139-na_GUFoVs.svg?v=1717077352", 94 | status: "active", 95 | createdAt: new Date("2024-06-08 11:23:45.936915 +00:00"), 96 | updatedAt: new Date("2024-06-08 11:23:45.936915 +00:00"), 97 | resourceNamespace: "library", 98 | resource: { 99 | resourceType: "libraryStaticImage", 100 | data: { 101 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset139-na_GUFoVs.svg?v=1717077352", 102 | }, 103 | }, 104 | }, 105 | { 106 | id: "f0877977-8ae3-424a-a750-518317d86337", 107 | cursor: 275, 108 | tags: ["bags", "arrows"], 109 | allowedPlanSlugs: ["all"], 110 | title: { "en-US": "Crescent Bag" }, 111 | description: null, 112 | mainImageSrc: 113 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset139_GUFoVs.svg?v=1717077352", 114 | status: "active", 115 | createdAt: new Date("2024-06-08 11:23:45.936915 +00:00"), 116 | updatedAt: new Date("2024-06-08 11:23:45.936915 +00:00"), 117 | resourceNamespace: "library", 118 | resource: { 119 | resourceType: "libraryStaticImage", 120 | data: { 121 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset139_GUFoVs.svg?v=1717077352", 122 | }, 123 | }, 124 | }, 125 | { 126 | id: "b089f006-21c3-4363-ad6b-89af726b3c17", 127 | cursor: 276, 128 | tags: ["bags", "no-arrows"], 129 | allowedPlanSlugs: ["all"], 130 | title: { "en-US": "Tote Bag" }, 131 | description: null, 132 | mainImageSrc: 133 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset140-na_qMvFUh.svg?v=1717077352", 134 | status: "active", 135 | createdAt: new Date("2024-06-08 11:25:48.677097 +00:00"), 136 | updatedAt: new Date("2024-06-08 11:25:48.677097 +00:00"), 137 | resourceNamespace: "library", 138 | resource: { 139 | resourceType: "libraryStaticImage", 140 | data: { 141 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset140-na_qMvFUh.svg?v=1717077352", 142 | }, 143 | }, 144 | }, 145 | { 146 | id: "28de1041-4233-409b-9416-1d4f7d87c99b", 147 | cursor: 278, 148 | tags: ["bags", "no-arrows"], 149 | allowedPlanSlugs: ["all"], 150 | title: { "en-US": "Satchel Bag" }, 151 | description: null, 152 | mainImageSrc: 153 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset141-na_fnidiJ.svg?v=1717077352", 154 | status: "active", 155 | createdAt: new Date("2024-06-08 11:26:32.911841 +00:00"), 156 | updatedAt: new Date("2024-06-08 11:26:32.911841 +00:00"), 157 | resourceNamespace: "library", 158 | resource: { 159 | resourceType: "libraryStaticImage", 160 | data: { 161 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset141-na_fnidiJ.svg?v=1717077352", 162 | }, 163 | }, 164 | }, 165 | { 166 | id: "9591b0a9-4e60-4ab0-9c5e-7ca118ccc553", 167 | cursor: 279, 168 | tags: ["bags", "arrows"], 169 | allowedPlanSlugs: ["all"], 170 | title: { "en-US": "Satchel Bag" }, 171 | description: null, 172 | mainImageSrc: 173 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset141_fnidiJ.svg?v=1717077352", 174 | status: "active", 175 | createdAt: new Date("2024-06-08 11:26:32.911841 +00:00"), 176 | updatedAt: new Date("2024-06-08 11:26:32.911841 +00:00"), 177 | 178 | resourceNamespace: "library", 179 | resource: { 180 | resourceType: "libraryStaticImage", 181 | data: { 182 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset141_fnidiJ.svg?v=1717077352", 183 | }, 184 | }, 185 | }, 186 | { 187 | id: "0cff4d2a-bbbf-4430-9cf5-6acb97395262", 188 | cursor: 280, 189 | tags: ["bags", "no-arrows"], 190 | allowedPlanSlugs: ["all"], 191 | title: { "en-US": "Bucket Bag" }, 192 | description: null, 193 | mainImageSrc: 194 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset142-na_czLUAk.svg?v=1717077352", 195 | status: "active", 196 | createdAt: new Date("2024-06-08 11:26:58.580202 +00:00"), 197 | updatedAt: new Date("2024-06-08 11:26:58.580202 +00:00"), 198 | resourceNamespace: "library", 199 | resource: { 200 | resourceType: "libraryStaticImage", 201 | data: { 202 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset142-na_czLUAk.svg?v=1717077352", 203 | }, 204 | }, 205 | }, 206 | { 207 | id: "9d885eba-3199-4529-bf77-d1dd87b5fb83", 208 | cursor: 281, 209 | tags: ["bags", "arrows"], 210 | allowedPlanSlugs: ["all"], 211 | title: { "en-US": "Bucket Bag" }, 212 | description: null, 213 | mainImageSrc: 214 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset142_czLUAk.svg?v=1717077352", 215 | status: "active", 216 | createdAt: new Date("2024-06-08 11:26:58.580202 +00:00"), 217 | updatedAt: new Date("2024-06-08 11:26:58.580202 +00:00"), 218 | resourceNamespace: "library", 219 | resource: { 220 | resourceType: "libraryStaticImage", 221 | data: { 222 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset142_czLUAk.svg?v=1717077352", 223 | }, 224 | }, 225 | }, 226 | { 227 | id: "40d58f96-53c7-4039-9584-e8d9b0fe18b8", 228 | cursor: 282, 229 | tags: ["bags", "no-arrows"], 230 | allowedPlanSlugs: ["all"], 231 | title: { "en-US": "Foldover Clutch" }, 232 | description: null, 233 | mainImageSrc: 234 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset143-na_xmWFgi.svg?v=1717077352", 235 | status: "active", 236 | createdAt: new Date("2024-06-08 11:27:30.257002 +00:00"), 237 | updatedAt: new Date("2024-06-08 11:27:30.257002 +00:00"), 238 | resourceNamespace: "library", 239 | resource: { 240 | resourceType: "libraryStaticImage", 241 | data: { 242 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset143-na_xmWFgi.svg?v=1717077352", 243 | }, 244 | }, 245 | }, 246 | { 247 | id: "57fb20f5-1637-4b96-9e31-0465158b21cb", 248 | cursor: 283, 249 | tags: ["bags", "arrows"], 250 | allowedPlanSlugs: ["all"], 251 | title: { "en-US": "Foldover Clutch" }, 252 | description: null, 253 | mainImageSrc: 254 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset143_xmWFgi.svg?v=1717077352", 255 | status: "active", 256 | createdAt: new Date("2024-06-08 11:27:30.257002 +00:00"), 257 | updatedAt: new Date("2024-06-08 11:27:30.257002 +00:00"), 258 | resourceNamespace: "library", 259 | resource: { 260 | resourceType: "libraryStaticImage", 261 | data: { 262 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset143_xmWFgi.svg?v=1717077352", 263 | }, 264 | }, 265 | }, 266 | { 267 | id: "f61435af-3443-46a9-9347-3a72bceef608", 268 | cursor: 284, 269 | tags: ["tops", "no-arrows"], 270 | allowedPlanSlugs: ["all"], 271 | title: { "en-US": "Baseball Jersey" }, 272 | description: null, 273 | mainImageSrc: 274 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset145-na_NtKRJi.svg?v=1717077352", 275 | status: "active", 276 | createdAt: new Date("2024-06-08 11:28:07.073194 +00:00"), 277 | updatedAt: new Date("2024-06-08 11:28:07.073194 +00:00"), 278 | resourceNamespace: "library", 279 | resource: { 280 | resourceType: "libraryStaticImage", 281 | data: { 282 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset145-na_NtKRJi.svg?v=1717077352", 283 | }, 284 | }, 285 | }, 286 | { 287 | id: "f2aff9ac-cf31-427d-b4a2-75a015f64459", 288 | cursor: 285, 289 | tags: ["tops", "arrows"], 290 | allowedPlanSlugs: ["all"], 291 | title: { "en-US": "Baseball Jersey" }, 292 | description: null, 293 | mainImageSrc: 294 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset145_NtKRJi.svg?v=1717077352", 295 | status: "active", 296 | createdAt: new Date("2024-06-08 11:28:07.073194 +00:00"), 297 | updatedAt: new Date("2024-06-08 11:28:07.073194 +00:00"), 298 | resourceNamespace: "library", 299 | resource: { 300 | resourceType: "libraryStaticImage", 301 | data: { 302 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset145_NtKRJi.svg?v=1717077352", 303 | }, 304 | }, 305 | }, 306 | { 307 | id: "b2425b54-202f-4b29-b4f6-e37e20044ca7", 308 | cursor: 286, 309 | tags: ["tops", "no-arrows"], 310 | allowedPlanSlugs: ["all"], 311 | title: { "en-US": "Baseball Tee Female" }, 312 | description: null, 313 | mainImageSrc: 314 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset146-na_PEbOTf.svg?v=1717077352", 315 | status: "active", 316 | createdAt: new Date("2024-06-08 11:28:30.829326 +00:00"), 317 | updatedAt: new Date("2024-06-08 11:28:30.829326 +00:00"), 318 | resourceNamespace: "library", 319 | resource: { 320 | resourceType: "libraryStaticImage", 321 | data: { 322 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset146-na_PEbOTf.svg?v=1717077352", 323 | }, 324 | }, 325 | }, 326 | { 327 | id: "841ef24f-9458-4c66-8072-2e475181f50f", 328 | cursor: 287, 329 | tags: ["tops", "arrows"], 330 | allowedPlanSlugs: ["all"], 331 | title: { "en-US": "Baseball Tee Female" }, 332 | description: null, 333 | mainImageSrc: 334 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset146_PEbOTf.svg?v=1717077352", 335 | status: "active", 336 | createdAt: new Date("2024-06-08 11:28:30.829326 +00:00"), 337 | updatedAt: new Date("2024-06-08 11:28:30.829326 +00:00"), 338 | resourceNamespace: "library", 339 | resource: { 340 | resourceType: "libraryStaticImage", 341 | data: { 342 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset146_PEbOTf.svg?v=1717077352", 343 | }, 344 | }, 345 | }, 346 | { 347 | id: "9b05e0bf-ec8e-4ff5-a86d-f076f7c6b559", 348 | cursor: 288, 349 | tags: ["tops", "no-arrows"], 350 | allowedPlanSlugs: ["all"], 351 | title: { "en-US": "Baseball Tee Male" }, 352 | description: null, 353 | mainImageSrc: 354 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset147-na_aDsSav.svg?v=1717077352", 355 | status: "active", 356 | createdAt: new Date("2024-06-08 11:28:54.898317 +00:00"), 357 | updatedAt: new Date("2024-06-08 11:28:54.898317 +00:00"), 358 | resourceNamespace: "library", 359 | resource: { 360 | resourceType: "libraryStaticImage", 361 | data: { 362 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset147-na_aDsSav.svg?v=1717077352", 363 | }, 364 | }, 365 | }, 366 | { 367 | id: "81ffe268-e233-4c32-820e-aaf9fb69dd31", 368 | cursor: 289, 369 | tags: ["tops", "arrows"], 370 | allowedPlanSlugs: ["all"], 371 | title: { "en-US": "Baseball Tee Male" }, 372 | description: null, 373 | mainImageSrc: 374 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset147_aDsSav.svg?v=1717077352", 375 | status: "active", 376 | createdAt: new Date("2024-06-08 11:28:54.898317 +00:00"), 377 | updatedAt: new Date("2024-06-08 11:28:54.898317 +00:00"), 378 | resourceNamespace: "library", 379 | resource: { 380 | resourceType: "libraryStaticImage", 381 | data: { 382 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset147_aDsSav.svg?v=1717077352", 383 | }, 384 | }, 385 | }, 386 | { 387 | id: "71c6d04b-46c0-47da-9ba7-27abf525d6cc", 388 | cursor: 290, 389 | tags: ["tops", "no-arrows"], 390 | allowedPlanSlugs: ["all"], 391 | title: { "en-US": "Football Jersey" }, 392 | description: null, 393 | mainImageSrc: 394 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset148-na_PjHNeD.svg?v=1717077352", 395 | status: "active", 396 | createdAt: new Date("2024-06-08 11:29:30.498990 +00:00"), 397 | updatedAt: new Date("2024-06-08 11:29:30.498990 +00:00"), 398 | resourceNamespace: "library", 399 | resource: { 400 | resourceType: "libraryStaticImage", 401 | data: { 402 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset148-na_PjHNeD.svg?v=1717077352", 403 | }, 404 | }, 405 | }, 406 | { 407 | id: "47fda7d8-406a-4379-9100-c56998d27294", 408 | cursor: 291, 409 | tags: ["tops", "arrows"], 410 | allowedPlanSlugs: ["all"], 411 | title: { "en-US": "Football Jersey" }, 412 | description: null, 413 | mainImageSrc: 414 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset148_PjHNeD.svg?v=1717077352", 415 | status: "active", 416 | createdAt: new Date("2024-06-08 11:29:30.498990 +00:00"), 417 | updatedAt: new Date("2024-06-08 11:29:30.498990 +00:00"), 418 | resourceNamespace: "library", 419 | resource: { 420 | resourceType: "libraryStaticImage", 421 | data: { 422 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset148_PjHNeD.svg?v=1717077352", 423 | }, 424 | }, 425 | }, 426 | { 427 | id: "efba58c2-11e1-43de-83a3-4bc8f23aa003", 428 | cursor: 277, 429 | tags: ["bags", "arrows"], 430 | allowedPlanSlugs: ["all"], 431 | title: { "en-US": "Tote Bag" }, 432 | description: null, 433 | mainImageSrc: 434 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset140_qMvFUh.svg?v=1717077352", 435 | status: "active", 436 | createdAt: new Date("2024-06-08 11:25:48.677097 +00:00"), 437 | updatedAt: new Date("2024-06-08 11:25:48.677097 +00:00"), 438 | resourceNamespace: "library", 439 | resource: { 440 | resourceType: "libraryStaticImage", 441 | data: { 442 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset140_qMvFUh.svg?v=1717077352", 443 | }, 444 | }, 445 | }, 446 | { 447 | id: "3ef3ec86-96b7-4197-a97c-bdedd0f6118b", 448 | cursor: 294, 449 | tags: ["accessories", "no-arrows"], 450 | allowedPlanSlugs: ["all"], 451 | title: { "en-US": "Diamond Ring" }, 452 | description: null, 453 | mainImageSrc: 454 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset164-na.svg?v=1717077352", 455 | status: "active", 456 | createdAt: new Date("2024-08-20 13:42:36.020377 +00:00"), 457 | updatedAt: new Date("2024-08-20 13:42:36.020377 +00:00"), 458 | resourceNamespace: "library", 459 | resource: { 460 | resourceType: "libraryStaticImage", 461 | data: { 462 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset164-na.svg?v=1717077352", 463 | }, 464 | }, 465 | }, 466 | { 467 | id: "b0b4f528-d4ab-4082-8a24-e3b60aacac11", 468 | cursor: 295, 469 | tags: ["accessories", "arrows"], 470 | allowedPlanSlugs: ["all"], 471 | title: { "en-US": "Diamond Ring" }, 472 | description: null, 473 | mainImageSrc: 474 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset164.svg?v=1717077352", 475 | status: "active", 476 | createdAt: new Date("2024-08-20 13:42:36.020377 +00:00"), 477 | updatedAt: new Date("2024-08-20 13:42:36.020377 +00:00"), 478 | resourceNamespace: "library", 479 | resource: { 480 | resourceType: "libraryStaticImage", 481 | data: { 482 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset164.svg?v=1717077352", 483 | }, 484 | }, 485 | }, 486 | { 487 | id: "d2564ae3-9380-4d07-bb1c-0887388f76cd", 488 | cursor: 296, 489 | tags: ["accessories", "no-arrows"], 490 | allowedPlanSlugs: ["all"], 491 | title: { "en-US": "Ring" }, 492 | description: null, 493 | mainImageSrc: 494 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset178-na.svg?v=1717077352", 495 | status: "active", 496 | createdAt: new Date("2024-08-20 13:42:47.812374 +00:00"), 497 | updatedAt: new Date("2024-08-20 13:42:47.812374 +00:00"), 498 | resourceNamespace: "library", 499 | resource: { 500 | resourceType: "libraryStaticImage", 501 | data: { 502 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset178-na.svg?v=1717077352", 503 | }, 504 | }, 505 | }, 506 | { 507 | id: "4b42b5cc-4d7c-42f6-8796-4beda8d82815", 508 | cursor: 297, 509 | tags: ["accessories", "arrows"], 510 | allowedPlanSlugs: ["all"], 511 | title: { "en-US": "Ring" }, 512 | description: null, 513 | mainImageSrc: 514 | "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset178.svg?v=1717077352", 515 | status: "active", 516 | createdAt: new Date("2024-08-20 13:42:47.812374 +00:00"), 517 | updatedAt: new Date("2024-08-20 13:42:47.812374 +00:00"), 518 | resourceNamespace: "library", 519 | resource: { 520 | resourceType: "libraryStaticImage", 521 | data: { 522 | src: "https://cdn.shopify.com/s/files/1/0873/5948/8306/files/Asset178.svg?v=1717077352", 523 | }, 524 | }, 525 | }, 526 | ] satisfies LibraryStaticImage[] 527 | 528 | export const handlePaginatedLibraryStaticImageResources = getPaginatedLibraryResources({ 529 | resources: libraryStaticImageResources, 530 | }) 531 | -------------------------------------------------------------------------------- /src/environment.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error 2 | export const locale = window?.shopify?.config?.locale 3 | export const rootLocale = locale?.split("-").at(0) ?? "en" 4 | export const shopifyApiBaseUrl = "https://mock.shop/api" 5 | -------------------------------------------------------------------------------- /src/hooks/actor-ref-creator.hook.tsx: -------------------------------------------------------------------------------- 1 | import { useSelector } from "@xstate/react" 2 | import type { ProviderProps } from "react" 3 | import { createContext, useContext } from "react" 4 | import type { ActorRef, SnapshotFrom } from "xstate" 5 | 6 | /** 7 | * @description allows to provide an actor context, and related hooks based on the actor ref 8 | */ 9 | export const createActorReferenceContext = < 10 | // biome-ignore lint/suspicious/noExplicitAny: 11 | TMachineReference extends ActorRef, 12 | >() => { 13 | const ActorReferenceContext = createContext( 14 | undefined as unknown as TMachineReference, 15 | ) 16 | const ActorRefProvider = ({ children, value }: ProviderProps) => ( 17 | {children} 18 | ) 19 | 20 | const useActorRefContext = () => { 21 | const context = useContext(ActorReferenceContext) 22 | 23 | if (context === undefined) { 24 | throw new Error("useActorRefContext must be used within a ActorReferenceProvider") 25 | } 26 | return context 27 | } 28 | 29 | const useActorRefSelector = ( 30 | selector: (emitted: SnapshotFrom) => T, 31 | compare?: (a: T, b: T) => boolean, 32 | ) => { 33 | const context = useActorRefContext() 34 | // FIXME: fix types 35 | // @ts-expect-error - false positive with xstate/react got some regression while bumping xstate version 36 | return useSelector(context, selector, compare) 37 | } 38 | 39 | return { 40 | useActorRefContext, 41 | useActorRefSelector, 42 | ActorRefProvider, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; -------------------------------------------------------------------------------- /src/machines/inspector/inspector.machine.tsx: -------------------------------------------------------------------------------- 1 | import { BlockStack, Box, Icon, InlineStack, Link, Page, Text } from "@shopify/polaris" 2 | import { CodeIcon, EmailIcon, EyeCheckMarkIcon, LinkIcon, ViewIcon } from "@shopify/polaris-icons" 3 | import { createBrowserInspector } from "@statelyai/inspect" 4 | import { useActor } from "@xstate/react" 5 | import type { FunctionComponent } from "react" 6 | import { type ActorOptions, type AnyActorLogic, assign, fromCallback, setup } from "xstate" 7 | import videoUrl from "../../assets/usage-stately-actors.mp4" 8 | type BrowserInspector = ReturnType 9 | 10 | type ExampleComponent = FunctionComponent<{ 11 | actorOptions: ActorOptions | undefined 12 | }> 13 | 14 | // Thanks, Baptiste, for this machine! - https://x.com/BDevessier 15 | const inspectorLauncherMachine = setup({ 16 | types: { 17 | context: {} as { 18 | updateId: number 19 | inspector: BrowserInspector | undefined 20 | }, 21 | events: {} as { type: "inspector.open" } | { type: "inspector.closed" }, 22 | }, 23 | actors: { 24 | "Wait for inspector window to be closed": fromCallback( 25 | ({ input, sendBack }) => { 26 | const timerId = setInterval(() => { 27 | const isInspectorClosed = input.inspector.adapter.targetWindow!.closed === true 28 | 29 | if (isInspectorClosed === true) { 30 | sendBack({ 31 | type: "inspector.closed", 32 | }) 33 | } 34 | }, 1_000) 35 | 36 | return () => { 37 | clearInterval(timerId) 38 | } 39 | }, 40 | ), 41 | }, 42 | actions: { 43 | "Create inspector and assign to context": assign({ 44 | inspector: () => createBrowserInspector(), 45 | }), 46 | "Increment update id in context": assign({ 47 | updateId: ({ context }) => context.updateId + 1, 48 | }), 49 | }, 50 | }).createMachine({ 51 | /** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOkwBsB7WSAYgNgAcxMAXSgJxMufwG0ADAF1EoRtVytclfKJAAPRAEYALAE4SAJgDsAZhUrtAVgBsugUoAcJgDQgAnst2aSAt293aBJ7Wu2qAXwC7NCw8QlIeMHx6fCYWdi4KakhBESQQcVhJaVkMxQRNEw0lUx01FW8BTSK7RwRLJRIjdwtdJSKjNV0TIOCQfEoIODlQnAJiOSycmTkCgFpbB0RFoJCMcYiyKhoIKYkpWfzEFU065RMBEms1SwFLTVMHn17+sfDibl597MO80AKKiMLm0p00SiUJkadwERhU5wQSmcrh6Kku7SsKiRmj6ASAA */ 52 | context: { 53 | updateId: 0, 54 | inspector: undefined, 55 | }, 56 | initial: "closed", 57 | states: { 58 | closed: { 59 | on: { 60 | "inspector.open": { 61 | target: "open", 62 | actions: ["Create inspector and assign to context", "Increment update id in context"], 63 | }, 64 | }, 65 | }, 66 | open: { 67 | invoke: { 68 | src: "Wait for inspector window to be closed", 69 | input: ({ context }) => { 70 | if (context.inspector === undefined) { 71 | throw new Error("Inspector must be defined in context") 72 | } 73 | 74 | return { 75 | inspector: context.inspector!, 76 | } 77 | }, 78 | }, 79 | on: { 80 | "inspector.closed": { 81 | target: "closed", 82 | }, 83 | }, 84 | }, 85 | }, 86 | }) 87 | 88 | const InspectorSetter = ({ 89 | inspector, 90 | Example, 91 | }: { 92 | inspector: BrowserInspector | undefined 93 | Example: ExampleComponent 94 | }) => { 95 | const actorOptions: ActorOptions | undefined = 96 | inspector === undefined 97 | ? undefined 98 | : { 99 | inspect: inspector.inspect as any, 100 | } 101 | 102 | return 103 | } 104 | 105 | const socials = [ 106 | { 107 | name: "Website", 108 | url: "https://djang0.dev", 109 | icon: LinkIcon, 110 | }, 111 | { 112 | name: "GitHub", 113 | url: "https://github.com/djang0dev", 114 | icon: CodeIcon, 115 | }, 116 | { 117 | name: "Mail", 118 | url: "mailto:kinane@djang0.dev", 119 | icon: EmailIcon, 120 | }, 121 | ] as const 122 | 123 | export const AppExampleSandbox = ({ 124 | Example, 125 | pageTitle, 126 | }: { Example: ExampleComponent; pageTitle: string }) => { 127 | const [state, send] = useActor(inspectorLauncherMachine) 128 | 129 | const isClosed = state.matches("closed") 130 | return ( 131 | { 136 | send({ type: "inspector.open" }) 137 | }, 138 | plain: true, 139 | outline: true, 140 | content: isClosed ? "Open Inspector" : "Visualizing", 141 | icon: isClosed ? ViewIcon : EyeCheckMarkIcon, 142 | disabled: !isClosed, 143 | helpText: isClosed ? ( 144 | "Visualize the machines on Stately.ai" 145 | ) : ( 146 |
147 | {/* biome-ignore lint/a11y/useMediaCaption: I don't have */} 148 |
150 | ), 151 | }, 152 | ]}> 153 | 154 | 159 | 160 | 161 | 162 | Made by{" "} 163 | 164 | Kinane Brevet 165 | {" "} 166 | - {new Date().getFullYear()} 167 | 168 | • 169 | 170 | {socials.map((social) => ( 171 | 177 | 178 | 179 | ))} 180 | 181 | 182 | 183 | 184 |
185 | ) 186 | } 187 | -------------------------------------------------------------------------------- /src/machines/resource-picker/resource-picker.context.ts: -------------------------------------------------------------------------------- 1 | import type { ActorRefFrom } from "xstate" 2 | import { createActorReferenceContext } from "../../hooks/actor-ref-creator.hook.tsx" 3 | import { resourcePickerMachineEditor } from "./resource-picker.machine.ts" 4 | 5 | export const { 6 | ActorRefProvider: ResourcePickerRefProvider, 7 | useActorRefContext: useResourcePickerRefContext, 8 | useActorRefSelector: useResourcePickerRefSelector, 9 | } = createActorReferenceContext>() 10 | -------------------------------------------------------------------------------- /src/machines/resource-picker/resource-picker.machine.ts: -------------------------------------------------------------------------------- 1 | import type { ModalProps } from "@shopify/polaris" 2 | import { create } from "mutative" 3 | import { assertEvent, assign, fromPromise, sendParent, setup } from "xstate" 4 | import type { 5 | LibraryQuery, 6 | LibraryResourceFilters, 7 | LibraryResourceTypeUnion, 8 | PageInfo, 9 | Resource, 10 | ResourceNamespace, 11 | ResourceType, 12 | ShopifyQuery, 13 | ShopifyResourceTypeUnion, 14 | } from "../../commons/entities" 15 | import { handleInvokeError } from "../../commons/http-errors" 16 | 17 | export interface GetResourcePickerItemsCbOutput { 18 | pageInfo: PageInfo 19 | libraryItems: Resource[] 20 | } 21 | export type ResourcePickerItemsCb = ( 22 | payload: DiscriminatedQueryUnion, 23 | ) => Promise 24 | export type DiscriminatedLibraryQuery = LibraryQuery & { queryType: "library" } 25 | export type DiscriminatedShopifyQuery = ShopifyQuery & { queryType: "shopify" } 26 | 27 | export type DiscriminatedQueryUnion = DiscriminatedLibraryQuery | DiscriminatedShopifyQuery 28 | 29 | export type ResourceSelectionType = "single" | "multiple" 30 | export interface ResourceSettings { 31 | resourceNamespace: ResourceNamespace 32 | resourceType: ResourceType 33 | selectionType: ResourceSelectionType 34 | } 35 | 36 | export type FiltersHandler = ( 37 | resourceType: LibraryResourceTypeUnion, 38 | ) => Promise 39 | 40 | export type ResourceSettingsV2 = { selectionType: ResourceSelectionType } & ( 41 | | { 42 | resourceNamespace: "library" 43 | resourceType: LibraryResourceTypeUnion 44 | queryHandler: ResourcePickerItemsCb 45 | filtersHandler: FiltersHandler 46 | } 47 | | { 48 | resourceNamespace: "shopify" 49 | resourceType: ShopifyResourceTypeUnion 50 | queryHandler: ResourcePickerItemsCb 51 | } 52 | ) 53 | 54 | export const isShopifyQueryQuery = ( 55 | payload: DiscriminatedQueryUnion["query"], 56 | ): payload is ShopifyQuery["query"] => { 57 | return typeof payload === "string" 58 | } 59 | export type ResourceUiMode = "resource-item" | "card" 60 | 61 | export interface UiSettings { 62 | modalSize: ModalProps["size"] | "medium" 63 | resourceUiMode: ResourceUiMode 64 | } 65 | export type ResourceSearchMachineInput = { 66 | uiSettings: UiSettings 67 | resourceSettings: ResourceSettingsV2 68 | } 69 | 70 | export const resourcePickerMachineEditor = setup({ 71 | types: { 72 | input: {} as ResourceSearchMachineInput, 73 | context: {} as ResourceSearchMachineInput & { 74 | filters: Record | undefined 75 | selectedItems: Map 76 | currentQuery: DiscriminatedQueryUnion 77 | currentResources: Resource[] 78 | currentPageInfo: PageInfo 79 | }, 80 | events: {} as 81 | | { 82 | type: "library.query.editQuery" 83 | payload: { 84 | query: string 85 | } 86 | } 87 | | { 88 | type: "rp.query.filters.edit" 89 | payload: { 90 | filterId: string 91 | value: string[] 92 | } 93 | } 94 | | { 95 | type: "library.query.filters.clearAll" 96 | } 97 | | { 98 | type: "open" 99 | payload: { 100 | selectedItems?: Map 101 | } 102 | } 103 | | { 104 | type: "close" 105 | } 106 | | { 107 | type: "library.item.select" 108 | payload: { 109 | itemId: string 110 | } 111 | } 112 | | { 113 | type: "library.item.unselect" 114 | payload: { 115 | itemId: string 116 | } 117 | } 118 | | { 119 | type: "library.items.loadMore" 120 | } 121 | | { 122 | type: "library.done" 123 | }, 124 | }, 125 | 126 | actors: { 127 | getLibraryItem: fromPromise( 128 | async ({ 129 | input, 130 | }: { 131 | input: { 132 | query: DiscriminatedQueryUnion 133 | handler: ResourcePickerItemsCb 134 | } 135 | }) => { 136 | return input.handler(input.query) 137 | }, 138 | ), 139 | 140 | getFilters: fromPromise( 141 | async ({ 142 | input, 143 | }: { 144 | input: { 145 | handler: FiltersHandler 146 | resourceType: LibraryResourceTypeUnion 147 | } 148 | }) => { 149 | return input.handler(input.resourceType) 150 | }, 151 | ), 152 | }, 153 | actions: { 154 | injectSelectedItems: assign(({ event, context }) => 155 | create(context, (draft) => { 156 | assertEvent(event, "open") 157 | draft.selectedItems = event.payload?.selectedItems ?? new Map() 158 | }), 159 | ), 160 | clearQueryEndCursor: assign(({ context }) => 161 | create(context, (draft) => { 162 | draft.currentQuery.endCursor = null 163 | }), 164 | ), 165 | editSearch: assign(({ context, event }) => { 166 | assertEvent(event, "library.query.editQuery") 167 | return create(context, (draft) => { 168 | draft.currentQuery.query = event.payload.query 169 | }) 170 | }), 171 | clearSelected: assign(({ context }) => 172 | create(context, (draft) => { 173 | draft.selectedItems.clear() 174 | }), 175 | ), 176 | clearFilters: assign(({ event, context }) => { 177 | assertEvent(event, "library.query.filters.clearAll") 178 | return create(context, (draft) => { 179 | if (draft.currentQuery.queryType === "library") { 180 | for (const filterToken in draft.currentQuery.filters) { 181 | draft.currentQuery.filters[filterToken as keyof LibraryResourceFilters["filters"]] = [] 182 | } 183 | } 184 | }) 185 | }), 186 | editFilter: assign(({ event, context }) => { 187 | assertEvent(event, "rp.query.filters.edit") 188 | return create(context, (draft) => { 189 | if (draft.currentQuery.queryType === "library") 190 | draft.currentQuery.filters[ 191 | event.payload.filterId as keyof LibraryResourceFilters["filters"] 192 | ] = event.payload.value 193 | }) 194 | }), 195 | sendSelectedItemsToParent: sendParent(({ context, self }) => { 196 | return { 197 | type: "rp.items.selected", 198 | payload: { 199 | selectedItems: context.selectedItems, 200 | senderId: self.id, 201 | resourceSettings: context.resourceSettings, 202 | }, 203 | } 204 | }), 205 | }, 206 | }).createMachine({ 207 | /** @xstate-layout N4IgpgJg5mDOIC5QCc4HsCuyDGYAKAltgNZjIB0AwgDZqyQDEaADmAHYDaADALqKjM6BAC4E0bfiAAeiAKwAmADQgAnogAcARnIAWAJwGAzADZjXQwHY9hvRYC+d5aliYc+IqQoB5VmwbZaem4+JBBBWBExCVCZBHlDLXJZLhSbWWNNK0NZZTUETXlbXWN1dRtNLgzNdR0HJ3QsXEISMnIfdioACzASBmDJcMjxSVj5At0dWUNNdOSa+Xkc1Q1F8gW9Masx6a5ZOpBnVyaPVva2Lp7iPs0QgSFRYZjEeS55CamZ4zmdBaW803U5Eq8jM+j0ZhMe0cBwabmanjavguvQ48luYXuURGiE0G3e01mXHmi1yz2s5AsILMXD0yU001s+0OjXcLW8SIAMmgAIYQABiBGowjIsAYEHEYHIBDYADc0KRyMy4Sd2R0ubyBUKRQhpXLsNyHpxeP1QoNDdi4uMdJMCV8iT8ScsEBZphSLGZZBZqpVsvZoUrjmzEWqefzBcLkKKyMg0BRmNQDQAzWMAW0VsMDCLO5HVYa1kZ1srQ+sNwRNdwi5qeCHSegpnvU8i0sk0xgSf0QFlKQPUsnBLqJpnkTIzrKznND0qgYolUqLCoDY9OE95U8LeoNUTLvAGmMeoFiFh02mBLfUGXienUFlJCGPbwWXzK1j09OsI5cLPhy5Dq7Y0+jWNyHjJNU3TT9lSDbNczXXVi03cRt3RM0sWrCwWyBYxFmqC8bGvW9klkchjCsI8dBIq83yheoIMzH9zgAUQgEQGGoAgACNkG5ZAVClYUU1gchaF5ABZWMwHLDFK1Qg8cWSLggWsCwj0pEibCUJ16WqJJPm9TRJlkBQPyOJdVUY5jhFYjiuJ48gAEcMDIXjIBEABFRyeMklD92kTtz0w7DzwKPCbyddQUmImkdF2UwuEmQpjK-FVg3MkRyAAZTAagelEf8GGQZh7I83jE3DEVyBc4QvL3aJZPyfQFJpSwVJBF0NlvLQdApcwCkMgwmwS-1R2-MzyCYtLMuy7BcunNjOO43iHKc8hSvzQSAjAbiAEFqGoarpJ82J9L0RqlJatT2qdaxAQqPRovBExLHSRLIPHDpxuEDKspyqcrPm2yRDANN6Cmqqd1NGqLQqcLyFsL5jEmXssI0vJNH07Rpmw91DEKSEXro0aPq+0HfrmmzeMBtMMDYEGcv2oZat8hBwqIqwSlpBHkfQ280fJNIaj7B6SPx0yUrGiziZ+vKyYW8hxTYCTwYrBmLUvbR5PMDnMmsDt8mqN53XSNStC9cwRZGsWicy7jsE6UnrNlpbbMq9ynPpqs6oqH5YZKd1SmUiwaRRztW10YEMi+GwbXN5LsytzacDtvKpFgYQDUlblEwjAAKeSAEp8uG2OkXjm2k6gd2ZKZ47TuanRVLa4PnRItYevIwoQXimOoJLiWtrYblqBUAAvMBJp+8Q+iVqSVerNWkhSTX0m17IefpYwKS+QP9PMYwOe7t7Us+-vB5HsfvumqJrmQyHqwqLDyFbLhMhMfR1FfHmaSIzHDNbWR9AWAfeiOZQxiVQOQAASmAYQyACBgBlGAGcCs5xygXEXHuv4IBgMlFAmBcCEHrngqWY009vKMyOrYG6XpXwtj3mCXW9JLBrHfovHGz8ZjURhLRUW0FQHiUgdA2B8DGApzTsKcgmcc4vC4AXRcFteGiX4bgoRCCICV0Op2V0p4cLBSvKFVG9dtAgkMtFBI1oiRAIoAAEQlFPG+B1yHPDbIYHS6R3QunWPhTS99yBaEWDUQOjZ6RQmhGwNAEA4CSDkSqXcDiLQAFo9C3niRvReaT0kpD9DREyFsaB0EgLE2edUSI8y7NoQ2LZwSvjip6SxKVCkeyZjYW8LwN6Ph0KUJshkjzDiGtw+RSJKDdBIA0qusQvF5C0ApDYr5wRvjGFwLJXCcnF0wZqCM8AIZxOrAkRqvY7rxAUOYXst4uwb3SP4qwvY4oJDqQo5i-5RkaPyOhBSmRcRvhdBkQwpzopJHkORCoshOo6EMIYO5vcRBPMcc6BIAUzy4T0beLCgITptkWLsZ+LZwV9JWRgo+ktL6PK2UUpmNRAQglpAoAyRhNA80KF1cld0db9UpBC96EtraJynNCqGQdfH1zUmMB6hgdAdWtL43qkw94VFubipK+LxZpRPkPUe49L4+TIVDeQR5fGvI+aC5+tg159lbsvAwfYEboXZecXM2DeV30CWsBsCgCivGBcYelHS1jwxqOpQOOLskKsPiAxR4DlH4LAA6z26E2kurGC8fxnrNJgtZvDF4BgEaMnla9YBdqlGCMjRAaNTNNiAl2PXQoWFyLTDFSm01xjPTKSJC2CxOaCbkBsQrEtox-7aAAfEbYNhBxr29sYrCbYtBlH0A4BwQA */ 208 | id: "resourcePicker", 209 | initial: "Closed", 210 | context: ({ input }) => ({ 211 | ...input, 212 | filters: undefined, 213 | selectedItems: new Map(), 214 | // TODO: Pagination with drizzle @see: https://orm.drizzle.team/learn/guides/limit-offset-pagination 215 | currentQuery: 216 | input.resourceSettings.resourceNamespace === "library" 217 | ? { 218 | queryType: "library", 219 | query: "", 220 | filters: { 221 | tags: [], 222 | }, 223 | first: 10, 224 | endCursor: null, 225 | } 226 | : { 227 | queryType: "shopify", 228 | query: "", 229 | endCursor: null, 230 | first: 10, 231 | }, 232 | currentResources: [], 233 | currentPageInfo: { 234 | endCursor: null, 235 | hasNextPage: true, 236 | hasPreviousPage: false, 237 | startCursor: "0", 238 | }, 239 | }), 240 | states: { 241 | Closed: { 242 | on: { 243 | open: { 244 | actions: ["injectSelectedItems"], 245 | target: "Open", 246 | }, 247 | }, 248 | }, 249 | Open: { 250 | on: { 251 | close: { 252 | target: "Closed", 253 | }, 254 | }, 255 | 256 | initial: "Check", 257 | states: { 258 | Check: { 259 | always: [ 260 | { 261 | target: "LoadFilters", 262 | guard: ({ context }) => { 263 | return !context.filters && context.resourceSettings.resourceNamespace === "library" 264 | }, 265 | }, 266 | { 267 | target: "Edit", 268 | guard: ({ context }) => { 269 | return context.currentResources.length > 0 270 | }, 271 | }, 272 | { 273 | target: "Loading", 274 | }, 275 | ], 276 | }, 277 | LoadFilters: { 278 | invoke: { 279 | src: "getFilters", 280 | input: ({ context }) => { 281 | if (context.resourceSettings.resourceNamespace !== "library") { 282 | throw new Error("filters not implemented for shopify resources") 283 | } 284 | return { 285 | handler: context.resourceSettings.filtersHandler, 286 | resourceType: context.resourceSettings.resourceType, 287 | } 288 | }, 289 | onError: { 290 | actions: handleInvokeError, 291 | target: "Edit", 292 | }, 293 | onDone: { 294 | actions: assign(({ event, context }) => 295 | create(context, (draft) => { 296 | draft.filters = event.output.filters 297 | }), 298 | ), 299 | target: "Check", 300 | }, 301 | }, 302 | }, 303 | Loading: { 304 | invoke: { 305 | input: ({ context }) => ({ 306 | handler: context.resourceSettings.queryHandler, 307 | query: context.currentQuery, 308 | }), 309 | src: "getLibraryItem", 310 | onDone: { 311 | actions: assign(({ event, context }) => 312 | create(context, (draft) => { 313 | draft.currentResources = event.output.libraryItems 314 | draft.currentPageInfo = event.output.pageInfo 315 | draft.currentQuery.endCursor = event.output.pageInfo.endCursor ?? null 316 | }), 317 | ), 318 | target: "Edit", 319 | }, 320 | onError: { 321 | actions: handleInvokeError, 322 | target: "Edit", 323 | }, 324 | }, 325 | }, 326 | Edit: { 327 | initial: "Selecting", 328 | on: { 329 | "library.items.loadMore": { 330 | target: "LoadMore", 331 | }, 332 | "library.query.editQuery": { 333 | actions: ["editSearch", "clearQueryEndCursor"], 334 | target: "#resourcePicker.Open.Edit.Searching", 335 | }, 336 | }, 337 | states: { 338 | Selecting: { 339 | on: { 340 | "rp.query.filters.edit": { 341 | actions: ["editFilter", "clearQueryEndCursor"], 342 | target: "#resourcePicker.Open.Loading", 343 | }, 344 | "library.query.filters.clearAll": { 345 | actions: ["clearFilters", "clearQueryEndCursor"], 346 | target: "#resourcePicker.Open.Loading", 347 | }, 348 | "library.item.select": { 349 | actions: assign(({ event, context }) => { 350 | const itemId = event.payload.itemId 351 | const item = context.currentResources.find((item) => item.id === itemId) 352 | 353 | if (!item) { 354 | throw new Error(`item ${itemId} not found in currentResources`) 355 | } 356 | 357 | return create(context, (draft) => { 358 | if (context.resourceSettings.selectionType === "single") { 359 | draft.selectedItems.clear() 360 | } 361 | draft.selectedItems.set(event.payload.itemId, item) 362 | }) 363 | }), 364 | target: "AnalyzeSelection", 365 | }, 366 | "library.item.unselect": { 367 | actions: assign(({ event, context }) => 368 | create(context, (draft) => { 369 | draft.selectedItems.delete(event.payload.itemId) 370 | }), 371 | ), 372 | }, 373 | "library.done": { 374 | target: "#resourcePicker.Done", 375 | }, 376 | }, 377 | }, 378 | Searching: { 379 | on: { 380 | "library.query.editQuery": { 381 | actions: ["clearQueryEndCursor", "editSearch"], 382 | target: "Searching", 383 | reenter: true, 384 | }, 385 | }, 386 | after: { 387 | 5e2: { 388 | target: "#resourcePicker.Open.Loading", 389 | }, 390 | }, 391 | }, 392 | AnalyzeSelection: { 393 | always: [ 394 | { 395 | guard: ({ context }) => { 396 | return ( 397 | // context.selectedItemIds.length === 1 && 398 | context.resourceSettings.selectionType === "single" 399 | ) 400 | }, 401 | 402 | target: "#resourcePicker.Done", 403 | }, 404 | { 405 | target: "Selecting", 406 | }, 407 | ], 408 | }, 409 | }, 410 | }, 411 | LoadMore: { 412 | initial: "Retrieve", 413 | states: { 414 | Retrieve: { 415 | invoke: { 416 | input: ({ context }) => ({ 417 | handler: context.resourceSettings.queryHandler, 418 | query: context.currentQuery, 419 | }), 420 | src: "getLibraryItem", 421 | onDone: { 422 | actions: assign(({ event, context }) => 423 | create(context, (draft) => { 424 | draft.currentResources.push(...event.output.libraryItems) 425 | draft.currentPageInfo = event.output.pageInfo 426 | draft.currentQuery.endCursor = event.output.pageInfo.endCursor ?? null 427 | }), 428 | ), 429 | target: "Retrieved", 430 | }, 431 | }, 432 | }, 433 | Retrieved: { 434 | after: { 435 | 2e2: { 436 | target: "#resourcePicker.Open.Edit", 437 | }, 438 | }, 439 | }, 440 | }, 441 | }, 442 | }, 443 | }, 444 | Done: { 445 | always: [ 446 | { 447 | actions: ["sendSelectedItemsToParent", "clearSelected"], 448 | target: "#resourcePicker.Closed", 449 | }, 450 | ], 451 | }, 452 | }, 453 | }) 454 | -------------------------------------------------------------------------------- /src/machines/resource-picker/resource-picker.view.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | type AppliedFilterInterface, 3 | BlockStack, 4 | Box, 5 | Checkbox, 6 | ChoiceList, 7 | Filters, 8 | Grid, 9 | Icon, 10 | InlineStack, 11 | Modal, 12 | Spinner, 13 | Tag, 14 | Text, 15 | TextField, 16 | Thumbnail, 17 | Tooltip, 18 | } from "@shopify/polaris" 19 | import { LockFilledIcon, SearchIcon } from "@shopify/polaris-icons" 20 | import React, { Fragment, type ReactElement, useMemo } from "react" 21 | import useInfiniteScroll from "react-infinite-scroll-hook" 22 | import * as R from "remeda" 23 | import type { ActorRefFrom } from "xstate" 24 | import { shopifyEditorConfig } from "../../shopify.config.ts" 25 | import { beautifyObjectName, beautifySlug, formatShopifyUrlImage } from "../../utils.ts" 26 | 27 | import { Resource } from "../../commons/entities.ts" 28 | import { 29 | ResourcePickerRefProvider, 30 | useResourcePickerRefContext, 31 | useResourcePickerRefSelector, 32 | } from "./resource-picker.context.ts" 33 | import type { ResourceUiMode, resourcePickerMachineEditor } from "./resource-picker.machine.ts" 34 | 35 | export const LibraryItem: React.FC<{ 36 | resourceItem: Resource 37 | onSelect: (selected: boolean) => void 38 | isSelected: boolean 39 | lock?: { 40 | content: ReactElement 41 | } 42 | mode: ResourceUiMode 43 | }> = ({ resourceItem, onSelect, isSelected, lock, mode }) => { 44 | const resourceItemTitle = 45 | typeof resourceItem.title === "string" ? resourceItem.title : resourceItem.title["en-US"] 46 | const resourceItemDescription = 47 | resourceItem.resourceNamespace === "library" 48 | ? resourceItem.description == null 49 | ? "" 50 | : resourceItem.description["en-US"] 51 | : "" 52 | return ( 53 | 54 | 136 | 137 | ) 138 | } 139 | 140 | export const LibraryFilters = () => { 141 | const { resourceNamespace } = useResourcePickerRefSelector( 142 | (state) => state.context.resourceSettings, 143 | ) 144 | const query = useResourcePickerRefSelector((state) => state.context.currentQuery.query) 145 | const queryFilters = useResourcePickerRefSelector((state) => { 146 | if (state.context.currentQuery.queryType === "library") { 147 | return state.context.currentQuery.filters 148 | } 149 | return undefined 150 | }) 151 | 152 | const filtersData = useResourcePickerRefSelector((state) => state.context.filters) 153 | const { send } = useResourcePickerRefContext() 154 | 155 | const filters = 156 | resourceNamespace === "shopify" 157 | ? [] 158 | : Object.entries(filtersData ?? {}).map(([filterId, filterData]) => { 159 | return { 160 | key: filterId, 161 | label: beautifyObjectName(filterId), 162 | filter: ( 163 | { 170 | return { label: filterToken, value: filterToken } 171 | }) 172 | } 173 | selected={queryFilters?.tags ?? []} 174 | onChange={(selected) => { 175 | send({ 176 | type: "rp.query.filters.edit", 177 | payload: { 178 | filterId, 179 | value: selected, 180 | }, 181 | }) 182 | }} 183 | allowMultiple 184 | /> 185 | ), 186 | shortcut: true, 187 | } 188 | }) 189 | 190 | const appliedFilters = useMemo(() => { 191 | if (queryFilters && filtersData) { 192 | return Object.entries(filtersData).reduce((acc, [filterId]) => { 193 | const selectedFilterData = queryFilters[filterId as keyof typeof queryFilters] 194 | if (!selectedFilterData || selectedFilterData?.length === 0) return acc 195 | 196 | return [ 197 | { 198 | key: filterId, 199 | label: 200 | R.isArray(selectedFilterData) && !R.isEmpty(selectedFilterData) 201 | ? `Selected: ${selectedFilterData.join(", ")}` 202 | : "", 203 | onRemove: () => { 204 | send({ 205 | type: "rp.query.filters.edit", 206 | payload: { 207 | filterId: filterId, 208 | value: [], 209 | }, 210 | }) 211 | }, 212 | }, 213 | ] 214 | }, [] as AppliedFilterInterface[]) 215 | } 216 | return [] 217 | }, [queryFilters, send, filtersData]) 218 | 219 | return ( 220 | 221 | 222 | 223 | } 227 | value={query ?? ""} 228 | onChange={(value) => { 229 | send({ 230 | type: "library.query.editQuery", 231 | payload: { 232 | query: value, 233 | }, 234 | }) 235 | }} 236 | /> 237 | 238 | {}} 241 | onQueryClear={() => {}} 242 | onClearAll={() => { 243 | send({ type: "library.query.filters.clearAll" }) 244 | }} 245 | hideQueryField={true} 246 | appliedFilters={appliedFilters} 247 | /> 248 | 249 | 250 | ) 251 | } 252 | 253 | export const ResourceItems = () => { 254 | const resourceItems = useResourcePickerRefSelector((state) => state.context.currentResources) 255 | const selectedItems = useResourcePickerRefSelector((state) => state.context.selectedItems) 256 | const uiSettings = useResourcePickerRefSelector((state) => state.context.uiSettings) 257 | const shopAssignedAppPlanSlug = "free" 258 | const { send } = useResourcePickerRefContext() 259 | return resourceItems.map((resourceItem) => { 260 | let lock 261 | if ( 262 | resourceItem.resourceNamespace === "shopify" || 263 | resourceItem.allowedPlanSlugs.includes(shopAssignedAppPlanSlug) || 264 | resourceItem.allowedPlanSlugs.includes("all") 265 | ) { 266 | lock = undefined 267 | } else { 268 | lock = { 269 | content: ( 270 | 276 | 280 | 281 | 282 | {/* FIXME: why does it refresh the whole page on redirect?*/} 283 | 284 | Upgrade 285 | 286 | 287 | 288 | 289 | ), 290 | } 291 | } 292 | 293 | return ( 294 | 295 | { 301 | if (selected) { 302 | send({ 303 | type: "library.item.select", 304 | payload: { 305 | itemId: resourceItem.id, 306 | }, 307 | }) 308 | return 309 | } 310 | 311 | send({ 312 | type: "library.item.unselect", 313 | payload: { 314 | itemId: resourceItem.id, 315 | }, 316 | }) 317 | }} 318 | /> 319 | 320 | ) 321 | }) 322 | } 323 | export const ResourcePickerMain = () => { 324 | const { send } = useResourcePickerRefContext() 325 | const isLoading = useResourcePickerRefSelector((state) => state.matches({ Open: "Loading" })) 326 | const isLoadMore = useResourcePickerRefSelector((state) => 327 | state.matches({ Open: { LoadMore: "Retrieved" } }), 328 | ) 329 | 330 | const uiSettings = useResourcePickerRefSelector((state) => state.context.uiSettings) 331 | 332 | const hasNextPage = useResourcePickerRefSelector( 333 | (state) => state.context.currentPageInfo.hasNextPage, 334 | ) 335 | 336 | const [intersectionRef, { rootRef }] = useInfiniteScroll({ 337 | loading: isLoading || isLoadMore, 338 | hasNextPage: hasNextPage, 339 | 340 | onLoadMore: () => { 341 | send({ 342 | type: "library.items.loadMore", 343 | }) 344 | }, 345 | // disabled: !!error, 346 | rootMargin: "0px 0px 20px 0px", 347 | }) 348 | 349 | if (isLoading) { 350 | return ( 351 |
352 | 353 | 354 | 355 |
356 | ) 357 | } 358 | 359 | return ( 360 |
361 | 362 | 363 | {uiSettings.resourceUiMode === "card" && ( 364 | 365 | 366 | 367 | )} 368 | {uiSettings.resourceUiMode === "resource-item" && ( 369 | 370 | 371 | 372 | 373 | 374 | )} 375 | 376 | 377 | {(isLoadMore || hasNextPage) && ( 378 |
379 | 380 | 381 | 382 | 383 | 384 |
385 | )} 386 |
387 | ) 388 | } 389 | 390 | export const ResourcePicker = () => { 391 | const state = useResourcePickerRefSelector((state) => state.value) 392 | const resourceType = useResourcePickerRefSelector( 393 | (state) => state.context.resourceSettings.resourceType, 394 | ) 395 | 396 | const uiSettings = useResourcePickerRefSelector((state) => state.context.uiSettings) 397 | const resourceSettings = useResourcePickerRefSelector((state) => state.context.resourceSettings) 398 | const { send } = useResourcePickerRefContext() 399 | 400 | return ( 401 | { 405 | send({ type: "close" }) 406 | }} 407 | primaryAction={ 408 | resourceSettings.selectionType === "multiple" 409 | ? { 410 | content: "Select", 411 | onAction: () => { 412 | send({ type: "library.done" }) 413 | }, 414 | } 415 | : undefined 416 | } 417 | size={uiSettings.modalSize === "medium" ? undefined : uiSettings.modalSize}> 418 |
419 | 420 | 421 |
422 |
423 | ) 424 | } 425 | export const ResourcePickerProvider: React.FC<{ 426 | actorRef: ActorRefFrom 427 | }> = ({ actorRef }) => ( 428 | 429 | 430 | 431 | ) 432 | -------------------------------------------------------------------------------- /src/machines/root/root.machine.context.tsx: -------------------------------------------------------------------------------- 1 | import type { ActorRefFrom } from "xstate" 2 | import { createActorReferenceContext } from "../../hooks/actor-ref-creator.hook.tsx" 3 | import { rootMachine } from "./root.machine.ts" 4 | 5 | export const { 6 | ActorRefProvider: RootProvider, 7 | useActorRefContext: useRootRef, 8 | useActorRefSelector: useRootSelector, 9 | } = createActorReferenceContext>() 10 | -------------------------------------------------------------------------------- /src/machines/root/root.machine.ts: -------------------------------------------------------------------------------- 1 | import request from "graphql-request" 2 | import { create } from "mutative" 3 | import toast from "react-hot-toast/headless" 4 | import set from "set-value" 5 | import { ActorRefFrom, assertEvent, assign, enqueueActions, setup, stopChild } from "xstate" 6 | import { 7 | CollectionQueryResponse, 8 | LibraryResourceTypeUnion, 9 | ProductsResponse, 10 | Resource, 11 | ShopifyResourceTypeUnion, 12 | } from "../../commons/entities" 13 | import { 14 | handlePaginatedLibraryStaticImageResources, 15 | libraryStaticImageResources, 16 | } from "../../data/library-static-images-resources.data" 17 | import { getShopifyCollections, getShopifyProducts } from "../../queries" 18 | import { getRandomString } from "../../utils" 19 | import { 20 | ResourceSearchMachineInput, 21 | ResourceSelectionType, 22 | ResourceSettings, 23 | ResourceSettingsV2, 24 | UiSettings, 25 | resourcePickerMachineEditor, 26 | } from "../resource-picker/resource-picker.machine" 27 | 28 | const rootPartialInput = { 29 | libraryStaticImage: { 30 | resourceSettings: { 31 | resourceNamespace: "library", 32 | resourceType: "libraryStaticImage", 33 | filtersHandler: async () => { 34 | return { 35 | filters: { tags: [...new Set(libraryStaticImageResources.flatMap((i) => i.tags))] }, 36 | } 37 | }, 38 | queryHandler: async (payload) => { 39 | if (payload.queryType === "shopify") { 40 | throw new Error( 41 | `Invalid library query received: ${JSON.stringify( 42 | payload, 43 | )}, might be due if you use the Shopify query formatting instead of the library one`, 44 | ) 45 | } 46 | 47 | const items = handlePaginatedLibraryStaticImageResources({ 48 | query: payload.query, 49 | first: payload.first, 50 | filters: { tags: payload.filters.tags ?? [] }, 51 | after: payload.endCursor ? Number(payload.endCursor) : undefined, 52 | }) 53 | 54 | console.log({ items }) 55 | return { 56 | libraryItems: items.data.map((i) => ({ 57 | tags: i.tags, 58 | updatedAt: new Date(i.updatedAt), 59 | cursor: i.cursor, 60 | resourceNamespace: "library", 61 | status: i.status, 62 | allowedPlanSlugs: ["all"], 63 | id: i.id, 64 | createdAt: i.createdAt, 65 | description: i.description, 66 | mainImageSrc: i.mainImageSrc, 67 | title: i.title, 68 | resource: { 69 | resourceType: "libraryStaticImage", 70 | title: i.title, 71 | data: { 72 | src: i.mainImageSrc, 73 | }, 74 | }, 75 | })), 76 | pageInfo: { 77 | hasNextPage: items.pageInfo.hasNextPage, 78 | hasPreviousPage: items.pageInfo.hasPreviousPage, 79 | endCursor: String(items.pageInfo.endCursor) || null, 80 | }, 81 | } 82 | }, 83 | }, 84 | }, 85 | product: { 86 | resourceSettings: { 87 | resourceNamespace: "shopify", 88 | queryHandler: async (payload) => { 89 | if (payload.queryType === "library") { 90 | throw new Error( 91 | `Invalid library query received: ${JSON.stringify( 92 | payload, 93 | )}, might be due if you use the Shopify query formatting instead of the library one`, 94 | ) 95 | } 96 | 97 | const data = (await request("https://mock.shop/api", getShopifyProducts, { 98 | after: payload.endCursor, 99 | first: payload.first, 100 | query: payload.query, 101 | })) as ProductsResponse 102 | 103 | return { 104 | libraryItems: data.products.edges.map((edge) => ({ 105 | allowedPlanSlugs: ["all"], 106 | id: edge.node.id, 107 | resourceNamespace: "shopify", 108 | mainImageSrc: edge.node.featuredImage.url, 109 | resource: { resourceType: "product", title: edge.node.title }, 110 | title: edge.node.title, 111 | })), 112 | pageInfo: data.products.pageInfo, 113 | } 114 | }, 115 | resourceType: "product", 116 | }, 117 | }, 118 | collection: { 119 | resourceSettings: { 120 | resourceNamespace: "shopify", 121 | queryHandler: async (payload) => { 122 | if (payload.queryType === "library") { 123 | throw new Error( 124 | `Invalid library query received: ${JSON.stringify( 125 | payload, 126 | )}, might be due if you use the Shopify query formatting instead of the library one`, 127 | ) 128 | } 129 | 130 | const data = (await request("https://mock.shop/api", getShopifyCollections, { 131 | after: payload.endCursor, 132 | first: payload.first, 133 | query: payload.query, 134 | })) as CollectionQueryResponse 135 | 136 | return { 137 | libraryItems: data.collections.edges.map((edge) => ({ 138 | allowedPlanSlugs: ["all"], 139 | id: edge.node.id, 140 | resourceNamespace: "shopify", 141 | mainImageSrc: edge.node.image.url, 142 | resource: { resourceType: "product", title: edge.node.title }, 143 | title: edge.node.title, 144 | })), 145 | pageInfo: data.collections.pageInfo, 146 | } 147 | }, 148 | resourceType: "collection", 149 | }, 150 | }, 151 | } satisfies { [type: string]: { resourceSettings: Partial } } 152 | 153 | export interface SpawnForm { 154 | uiSettings: UiSettings 155 | resourceType: ShopifyResourceTypeUnion 156 | resourceSelectionType: ResourceSelectionType 157 | } 158 | 159 | export interface ResourcePickerValue { 160 | actorRef: ActorRefFrom 161 | latestSelectedItemIds: Set 162 | } 163 | 164 | export const rootMachine = setup({ 165 | types: { 166 | events: {} as 167 | | { 168 | type: "rp.spawn" 169 | } 170 | | { 171 | type: "rp.open" 172 | payload: { 173 | id: string 174 | } 175 | } 176 | | { 177 | type: "rp.kill" 178 | payload: { 179 | id: string 180 | } 181 | } 182 | | { 183 | type: "rp.items.selected" 184 | payload: { 185 | senderId: string 186 | selectedItems: Map 187 | resourceSettings: ResourceSettings 188 | } 189 | } 190 | | { 191 | // TODO: better typesafety 192 | type: "rpSpawnForm.edit" 193 | payload: { 194 | key: string 195 | value: string 196 | } 197 | }, 198 | 199 | context: {} as { 200 | spawnForm: { 201 | uiSettings: UiSettings 202 | resourceType: ShopifyResourceTypeUnion | LibraryResourceTypeUnion 203 | resourceSelectionType: ResourceSelectionType 204 | } 205 | resourcePickers: Map< 206 | string, 207 | { 208 | actorRef: ActorRefFrom 209 | latestSelectedItems: Map 210 | } 211 | > 212 | }, 213 | }, 214 | actions: { 215 | openResourcePicker: enqueueActions(({ context, enqueue, event }) => { 216 | assertEvent(event, "rp.open") 217 | const rp = context.resourcePickers.get(event.payload.id) 218 | if (!rp) return 219 | 220 | enqueue.sendTo(rp.actorRef, { 221 | type: "open", 222 | payload: { 223 | selectedItems: rp.latestSelectedItems, 224 | }, 225 | }) 226 | }), 227 | rpInsertLastSelectedItemsIds: assign(({ event, context }) => { 228 | assertEvent(event, "rp.items.selected") 229 | const id = event.payload.senderId 230 | return create(context, (draft) => { 231 | const resourcePicker = draft.resourcePickers.get(id) 232 | if (!resourcePicker) return 233 | resourcePicker.latestSelectedItems = event.payload.selectedItems 234 | }) 235 | }), 236 | 237 | logContext: ({ context }) => { 238 | console.log({ context }) 239 | }, 240 | 241 | killResourcePicker: assign(({ event, context }) => { 242 | assertEvent(event, "rp.kill") 243 | const actorId = event.payload.id 244 | stopChild(actorId) 245 | return create(context, (draft) => { 246 | draft.resourcePickers.delete(actorId) 247 | }) 248 | }), 249 | 250 | spawnResourcePicker: assign(({ context, event, spawn }) => { 251 | assertEvent(event, "rp.spawn") 252 | const systemId = getRandomString() 253 | const { spawnForm } = context 254 | // @ts-expect-error id wrong typing from xstate 255 | const actorRef = spawn(resourcePickerMachineEditor, { 256 | input: { 257 | resourceSettings: { 258 | ...rootPartialInput[spawnForm.resourceType]?.resourceSettings, 259 | selectionType: spawnForm.resourceSelectionType, 260 | } as ResourceSettingsV2, 261 | uiSettings: spawnForm.uiSettings, 262 | } satisfies ResourceSearchMachineInput, 263 | 264 | id: systemId, 265 | }) 266 | 267 | return create(context, (draft) => { 268 | draft.resourcePickers.set(actorRef.id, { 269 | // @ts-expect-error id wrong typing from xstate 270 | actorRef: actorRef, 271 | latestSelectedItems: new Map(), 272 | }) 273 | }) 274 | }), 275 | editRpSpawnerForm: assign(({ context, event }) => { 276 | assertEvent(event, "rpSpawnForm.edit") 277 | 278 | console.log(event) 279 | return create(context, (draft) => { 280 | set(draft.spawnForm, event.payload.key, event.payload.value) 281 | }) 282 | }), 283 | }, 284 | }).createMachine({ 285 | /** @xstate-layout N4IgpgJg5mDOIC5QCcD2qAuA6AlhANmAMTIAOAyqQIYDuAdgGKrIC2WkOGA2gAwC6iUKVSxOOVHUEgAHogBsADiwAmAMwLlATgCsAFh6bVygOwBGUwBoQAT3lms24wtOPTW4wdUBfL1bSZcAmIyXAwwFlgsWDBCAGMwiF4BJBBhUQxxSRTZBF1lK1sEPSVTM00eZR4KhSrlHz90bDxCElIsVFIwOiSpNLEJKRy5Yyw5OR5TOW1NDVNNeYLEPN0sYym5XUVjbQVNUx5depB-JqDWrABrHHx8HpS+jIHsxGMV5XXVOUMTExdFhFUEywqmmqj2r12zgUciOJ0CLRCsGo9DuQhE-SyoCGqhUpgUa20Lm0ql02hM-1KIx0qlMnzkykqxhMsMa8OCbSRtDoADVlKjUujHpiZIhtNpgWCFLpjPNPnptP9nA4qlVdOplNoDDwFD5fCA6KgIHApCdeoLMoNEABaOT-G1YFWOp1VYwsgLNMBm9IW54INzKLCaAnacZ4zSkjb-GWaQNS3T+kNyPHaXVeIA */ 286 | id: "root", 287 | initial: "idle", 288 | context: { 289 | resourcePickers: new Map(), 290 | spawnForm: { 291 | uiSettings: { 292 | modalSize: "large", 293 | resourceUiMode: "resource-item", 294 | }, 295 | resourceSelectionType: "multiple", 296 | resourceType: "product", 297 | }, 298 | }, 299 | states: { 300 | idle: { 301 | on: { 302 | "rpSpawnForm.edit": { 303 | actions: ["editRpSpawnerForm", "logContext"], 304 | }, 305 | "rp.items.selected": { 306 | actions: [ 307 | ({ event }) => { 308 | toast.success( 309 | `Root actor received the selected items ids from ${event.payload.senderId}`, 310 | ) 311 | }, 312 | "rpInsertLastSelectedItemsIds", 313 | ], 314 | }, 315 | "rp.open": { 316 | actions: [ 317 | "openResourcePicker", 318 | ({ event }) => { 319 | toast.success(`Resource picker ${event.payload.id} opened from root actor`) 320 | }, 321 | ], 322 | }, 323 | "rp.kill": { 324 | actions: [ 325 | "killResourcePicker", 326 | ({ event }) => { 327 | toast.error(`Resource Picker ${event.payload.id} killed from root actor`) 328 | }, 329 | ], 330 | }, 331 | 332 | "rp.spawn": { 333 | actions: [ 334 | "spawnResourcePicker", 335 | () => toast.success("Resource picker spawned from root actor"), 336 | ], 337 | }, 338 | }, 339 | }, 340 | }, 341 | }) 342 | -------------------------------------------------------------------------------- /src/machines/root/root.view.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | BlockStack, 3 | Box, 4 | Button, 5 | Card, 6 | ChoiceList, 7 | InlineStack, 8 | Layout, 9 | List, 10 | Select, 11 | Text, 12 | } from "@shopify/polaris" 13 | import { useActorRef } from "@xstate/react" 14 | import { Fragment, useMemo } from "react" 15 | import type { FC } from "react" 16 | import { ActorOptions, AnyActorLogic } from "xstate" 17 | 18 | import { getRandomNumberFromN } from "../../utils.ts" 19 | import { ResourcePickerProvider } from "../resource-picker/resource-picker.view.tsx" 20 | import { RootProvider, useRootRef, useRootSelector } from "./root.machine.context.tsx" 21 | import { ResourcePickerValue, rootMachine } from "./root.machine.ts" 22 | 23 | interface Props { 24 | actorOptions: ActorOptions | undefined 25 | } 26 | export const Root = ({ actorOptions }: Props) => { 27 | const rootActorRef = useActorRef(rootMachine, actorOptions) 28 | return ( 29 | 30 | 31 | 32 | ) 33 | } 34 | 35 | export const RootForm = () => { 36 | const spawnForm = useRootSelector((snapshot) => snapshot.context.spawnForm) 37 | const { send } = useRootRef() 38 | return ( 39 | 40 | 41 | { 46 | const selected = v.at(0) 47 | if (!selected) return 48 | send({ 49 | type: "rpSpawnForm.edit", 50 | payload: { 51 | key: "resourceType", 52 | value: selected, 53 | }, 54 | }) 55 | }} 56 | choices={[ 57 | { label: "Product", value: "product" }, 58 | { label: "Collection", value: "collection" }, 59 | { label: "Static Image", value: "libraryStaticImage" }, 60 | ]} 61 | /> 62 |