Shih-hungg commited on
Commit
8b65a0f
·
1 Parent(s): a4309f4

Migrate to shadcn

Browse files
.gitignore CHANGED
@@ -33,6 +33,10 @@ yarn-error.log*
33
  # env files (can opt-in for committing if needed)
34
  .env*
35
 
 
 
 
 
36
  # vercel
37
  .vercel
38
 
 
33
  # env files (can opt-in for committing if needed)
34
  .env*
35
 
36
+ # local settings files
37
+ settings.local.json
38
+ settings.json
39
+
40
  # vercel
41
  .vercel
42
 
components.json ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema.json",
3
+ "style": "new-york",
4
+ "rsc": true,
5
+ "tsx": true,
6
+ "tailwind": {
7
+ "config": "",
8
+ "css": "src/app/globals.css",
9
+ "baseColor": "neutral",
10
+ "cssVariables": true,
11
+ "prefix": ""
12
+ },
13
+ "aliases": {
14
+ "components": "@/components",
15
+ "utils": "@/lib/utils",
16
+ "ui": "@/components/ui",
17
+ "lib": "@/lib",
18
+ "hooks": "@/hooks"
19
+ },
20
+ "iconLibrary": "lucide"
21
+ }
package-lock.json CHANGED
@@ -10,10 +10,24 @@
10
  "dependencies": {
11
  "@ai-sdk/openai": "^2.0.0",
12
  "@ai-sdk/react": "^2.0.1",
 
 
 
 
 
 
 
 
13
  "ai": "^5.0.1",
 
 
 
 
14
  "next": "15.4.5",
15
  "react": "19.1.0",
16
  "react-dom": "19.1.0",
 
 
17
  "zod": "^3.25.76"
18
  },
19
  "devDependencies": {
@@ -25,6 +39,7 @@
25
  "eslint": "^9",
26
  "eslint-config-next": "15.4.5",
27
  "tailwindcss": "^4",
 
28
  "typescript": "^5"
29
  }
30
  },
@@ -302,6 +317,51 @@
302
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
303
  }
304
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
305
  "node_modules/@humanfs/core": {
306
  "version": "0.19.1",
307
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@humanfs/core/-/core-0.19.1.tgz",
@@ -749,6 +809,647 @@
749
  "node": ">=8.0.0"
750
  }
751
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
752
  "node_modules/@rtsao/scc": {
753
  "version": "1.1.0",
754
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@rtsao/scc/-/scc-1.1.0.tgz",
@@ -766,6 +1467,11 @@
766
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@standard-schema/spec/-/spec-1.0.0.tgz",
767
  "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="
768
  },
 
 
 
 
 
769
  "node_modules/@swc/helpers": {
770
  "version": "0.5.15",
771
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -1067,7 +1773,7 @@
1067
  "version": "19.1.9",
1068
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react/-/react-19.1.9.tgz",
1069
  "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==",
1070
- "dev": true,
1071
  "dependencies": {
1072
  "csstype": "^3.0.2"
1073
  }
@@ -1076,7 +1782,7 @@
1076
  "version": "19.1.7",
1077
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react-dom/-/react-dom-19.1.7.tgz",
1078
  "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
1079
- "dev": true,
1080
  "peerDependencies": {
1081
  "@types/react": "^19.0.0"
1082
  }
@@ -1550,6 +2256,17 @@
1550
  "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1551
  "dev": true
1552
  },
 
 
 
 
 
 
 
 
 
 
 
1553
  "node_modules/aria-query": {
1554
  "version": "5.3.2",
1555
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/aria-query/-/aria-query-5.3.2.tgz",
@@ -1840,11 +2557,27 @@
1840
  "node": ">=18"
1841
  }
1842
  },
 
 
 
 
 
 
 
 
1843
  "node_modules/client-only": {
1844
  "version": "0.0.1",
1845
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/client-only/-/client-only-0.0.1.tgz",
1846
  "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
1847
  },
 
 
 
 
 
 
 
 
1848
  "node_modules/color": {
1849
  "version": "4.2.3",
1850
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/color/-/color-4.2.3.tgz",
@@ -1892,6 +2625,11 @@
1892
  "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1893
  "dev": true
1894
  },
 
 
 
 
 
1895
  "node_modules/cross-spawn": {
1896
  "version": "7.0.6",
1897
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -1910,7 +2648,7 @@
1910
  "version": "3.1.3",
1911
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/csstype/-/csstype-3.1.3.tgz",
1912
  "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
1913
- "dev": true
1914
  },
1915
  "node_modules/damerau-levenshtein": {
1916
  "version": "1.0.8",
@@ -2028,6 +2766,11 @@
2028
  "node": ">=8"
2029
  }
2030
  },
 
 
 
 
 
2031
  "node_modules/doctrine": {
2032
  "version": "2.1.0",
2033
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/doctrine/-/doctrine-2.1.0.tgz",
@@ -2040,6 +2783,46 @@
2040
  "node": ">=0.10.0"
2041
  }
2042
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2043
  "node_modules/dunder-proto": {
2044
  "version": "1.0.1",
2045
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -2812,6 +3595,14 @@
2812
  "node": ">= 0.4"
2813
  }
2814
  },
 
 
 
 
 
 
 
 
2815
  "node_modules/get-proto": {
2816
  "version": "1.0.1",
2817
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/get-proto/-/get-proto-1.0.1.tgz",
@@ -2963,6 +3754,15 @@
2963
  "node": ">= 0.4"
2964
  }
2965
  },
 
 
 
 
 
 
 
 
 
2966
  "node_modules/hasown": {
2967
  "version": "2.0.2",
2968
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/hasown/-/hasown-2.0.2.tgz",
@@ -2984,6 +3784,11 @@
2984
  "node": ">= 4"
2985
  }
2986
  },
 
 
 
 
 
2987
  "node_modules/import-fresh": {
2988
  "version": "3.3.1",
2989
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -3006,6 +3811,11 @@
3006
  "node": ">=0.8.19"
3007
  }
3008
  },
 
 
 
 
 
3009
  "node_modules/internal-slot": {
3010
  "version": "1.1.0",
3011
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/internal-slot/-/internal-slot-1.1.0.tgz",
@@ -3441,6 +4251,17 @@
3441
  "node": ">=4.0"
3442
  }
3443
  },
 
 
 
 
 
 
 
 
 
 
 
3444
  "node_modules/keyv": {
3445
  "version": "4.5.4",
3446
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/keyv/-/keyv-4.5.4.tgz",
@@ -3481,6 +4302,14 @@
3481
  "node": ">= 0.8.0"
3482
  }
3483
  },
 
 
 
 
 
 
 
 
3484
  "node_modules/lightningcss": {
3485
  "version": "1.30.1",
3486
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lightningcss/-/lightningcss-1.30.1.tgz",
@@ -3635,6 +4464,14 @@
3635
  "loose-envify": "cli.js"
3636
  }
3637
  },
 
 
 
 
 
 
 
 
3638
  "node_modules/magic-string": {
3639
  "version": "0.30.17",
3640
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/magic-string/-/magic-string-0.30.17.tgz",
@@ -3675,6 +4512,11 @@
3675
  "node": ">=8.6"
3676
  }
3677
  },
 
 
 
 
 
3678
  "node_modules/minimatch": {
3679
  "version": "3.1.2",
3680
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/minimatch/-/minimatch-3.1.2.tgz",
@@ -4005,6 +4847,11 @@
4005
  "node": ">=10"
4006
  }
4007
  },
 
 
 
 
 
4008
  "node_modules/parent-module": {
4009
  "version": "1.0.1",
4010
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/parent-module/-/parent-module-1.0.1.tgz",
@@ -4087,6 +4934,11 @@
4087
  "node": ">= 0.8.0"
4088
  }
4089
  },
 
 
 
 
 
4090
  "node_modules/prop-types": {
4091
  "version": "15.8.1",
4092
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/prop-types/-/prop-types-15.8.1.tgz",
@@ -4132,12 +4984,108 @@
4132
  "react": "^19.1.0"
4133
  }
4134
  },
 
 
 
 
 
 
 
 
 
 
 
4135
  "node_modules/react-is": {
4136
  "version": "16.13.1",
4137
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-is/-/react-is-16.13.1.tgz",
4138
  "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
4139
  "dev": true
4140
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4141
  "node_modules/reflect.getprototypeof": {
4142
  "version": "1.0.10",
4143
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -4241,6 +5189,11 @@
4241
  "node": ">=0.4"
4242
  }
4243
  },
 
 
 
 
 
4244
  "node_modules/safe-push-apply": {
4245
  "version": "1.0.0",
4246
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
@@ -4268,6 +5221,11 @@
4268
  "node": ">= 0.4"
4269
  }
4270
  },
 
 
 
 
 
4271
  "node_modules/scheduler": {
4272
  "version": "0.26.0",
4273
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/scheduler/-/scheduler-0.26.0.tgz",
@@ -4331,6 +5289,11 @@
4331
  "node": ">= 0.4"
4332
  }
4333
  },
 
 
 
 
 
4334
  "node_modules/sharp": {
4335
  "version": "0.34.3",
4336
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/sharp/-/sharp-0.34.3.tgz",
@@ -4487,6 +5450,14 @@
4487
  "node": ">= 0.4"
4488
  }
4489
  },
 
 
 
 
 
 
 
 
4490
  "node_modules/string.prototype.includes": {
4491
  "version": "2.0.1",
4492
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
@@ -4621,6 +5592,11 @@
4621
  "node": ">= 0.4"
4622
  }
4623
  },
 
 
 
 
 
4624
  "node_modules/tailwindcss": {
4625
  "version": "4.1.11",
4626
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tailwindcss/-/tailwindcss-4.1.11.tgz",
@@ -4738,6 +5714,12 @@
4738
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tslib/-/tslib-2.8.1.tgz",
4739
  "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
4740
  },
 
 
 
 
 
 
4741
  "node_modules/type-check": {
4742
  "version": "0.4.0",
4743
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/type-check/-/type-check-0.4.0.tgz",
@@ -4889,6 +5871,52 @@
4889
  "punycode": "^2.1.0"
4890
  }
4891
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4892
  "node_modules/which": {
4893
  "version": "2.0.2",
4894
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/which/-/which-2.0.2.tgz",
@@ -4986,6 +6014,22 @@
4986
  "node": ">=0.10.0"
4987
  }
4988
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4989
  "node_modules/yallist": {
4990
  "version": "5.0.0",
4991
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/yallist/-/yallist-5.0.0.tgz",
@@ -5224,6 +6268,44 @@
5224
  "levn": "^0.4.1"
5225
  }
5226
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5227
  "@humanfs/core": {
5228
  "version": "0.19.1",
5229
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@humanfs/core/-/core-0.19.1.tgz",
@@ -5574,6 +6656,318 @@
5574
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@opentelemetry/api/-/api-1.9.0.tgz",
5575
  "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="
5576
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5577
  "@rtsao/scc": {
5578
  "version": "1.1.0",
5579
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@rtsao/scc/-/scc-1.1.0.tgz",
@@ -5591,6 +6985,11 @@
5591
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@standard-schema/spec/-/spec-1.0.0.tgz",
5592
  "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="
5593
  },
 
 
 
 
 
5594
  "@swc/helpers": {
5595
  "version": "0.5.15",
5596
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@swc/helpers/-/helpers-0.5.15.tgz",
@@ -5838,7 +7237,7 @@
5838
  "version": "19.1.9",
5839
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react/-/react-19.1.9.tgz",
5840
  "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==",
5841
- "dev": true,
5842
  "requires": {
5843
  "csstype": "^3.0.2"
5844
  }
@@ -5847,7 +7246,7 @@
5847
  "version": "19.1.7",
5848
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react-dom/-/react-dom-19.1.7.tgz",
5849
  "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
5850
- "dev": true,
5851
  "requires": {}
5852
  },
5853
  "@typescript-eslint/eslint-plugin": {
@@ -6226,6 +7625,14 @@
6226
  "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
6227
  "dev": true
6228
  },
 
 
 
 
 
 
 
 
6229
  "aria-query": {
6230
  "version": "5.3.2",
6231
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/aria-query/-/aria-query-5.3.2.tgz",
@@ -6456,11 +7863,24 @@
6456
  "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
6457
  "dev": true
6458
  },
 
 
 
 
 
 
 
 
6459
  "client-only": {
6460
  "version": "0.0.1",
6461
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/client-only/-/client-only-0.0.1.tgz",
6462
  "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
6463
  },
 
 
 
 
 
6464
  "color": {
6465
  "version": "4.2.3",
6466
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/color/-/color-4.2.3.tgz",
@@ -6502,6 +7922,11 @@
6502
  "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
6503
  "dev": true
6504
  },
 
 
 
 
 
6505
  "cross-spawn": {
6506
  "version": "7.0.6",
6507
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -6517,7 +7942,7 @@
6517
  "version": "3.1.3",
6518
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/csstype/-/csstype-3.1.3.tgz",
6519
  "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
6520
- "dev": true
6521
  },
6522
  "damerau-levenshtein": {
6523
  "version": "1.0.8",
@@ -6606,6 +8031,11 @@
6606
  "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
6607
  "devOptional": true
6608
  },
 
 
 
 
 
6609
  "doctrine": {
6610
  "version": "2.1.0",
6611
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/doctrine/-/doctrine-2.1.0.tgz",
@@ -6615,6 +8045,39 @@
6615
  "esutils": "^2.0.2"
6616
  }
6617
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6618
  "dunder-proto": {
6619
  "version": "1.0.1",
6620
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -7234,6 +8697,11 @@
7234
  "math-intrinsics": "^1.1.0"
7235
  }
7236
  },
 
 
 
 
 
7237
  "get-proto": {
7238
  "version": "1.0.1",
7239
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/get-proto/-/get-proto-1.0.1.tgz",
@@ -7352,6 +8820,15 @@
7352
  "has-symbols": "^1.0.3"
7353
  }
7354
  },
 
 
 
 
 
 
 
 
 
7355
  "hasown": {
7356
  "version": "2.0.2",
7357
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/hasown/-/hasown-2.0.2.tgz",
@@ -7367,6 +8844,11 @@
7367
  "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
7368
  "dev": true
7369
  },
 
 
 
 
 
7370
  "import-fresh": {
7371
  "version": "3.3.1",
7372
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -7383,6 +8865,11 @@
7383
  "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
7384
  "dev": true
7385
  },
 
 
 
 
 
7386
  "internal-slot": {
7387
  "version": "1.1.0",
7388
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/internal-slot/-/internal-slot-1.1.0.tgz",
@@ -7725,6 +9212,17 @@
7725
  "object.values": "^1.1.6"
7726
  }
7727
  },
 
 
 
 
 
 
 
 
 
 
 
7728
  "keyv": {
7729
  "version": "4.5.4",
7730
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/keyv/-/keyv-4.5.4.tgz",
@@ -7759,6 +9257,14 @@
7759
  "type-check": "~0.4.0"
7760
  }
7761
  },
 
 
 
 
 
 
 
 
7762
  "lightningcss": {
7763
  "version": "1.30.1",
7764
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lightningcss/-/lightningcss-1.30.1.tgz",
@@ -7872,6 +9378,12 @@
7872
  "js-tokens": "^3.0.0 || ^4.0.0"
7873
  }
7874
  },
 
 
 
 
 
 
7875
  "magic-string": {
7876
  "version": "0.30.17",
7877
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/magic-string/-/magic-string-0.30.17.tgz",
@@ -7903,6 +9415,11 @@
7903
  "picomatch": "^2.3.1"
7904
  }
7905
  },
 
 
 
 
 
7906
  "minimatch": {
7907
  "version": "3.1.2",
7908
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/minimatch/-/minimatch-3.1.2.tgz",
@@ -8125,6 +9642,11 @@
8125
  "p-limit": "^3.0.2"
8126
  }
8127
  },
 
 
 
 
 
8128
  "parent-module": {
8129
  "version": "1.0.1",
8130
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/parent-module/-/parent-module-1.0.1.tgz",
@@ -8186,6 +9708,11 @@
8186
  "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
8187
  "dev": true
8188
  },
 
 
 
 
 
8189
  "prop-types": {
8190
  "version": "15.8.1",
8191
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/prop-types/-/prop-types-15.8.1.tgz",
@@ -8222,12 +9749,69 @@
8222
  "scheduler": "^0.26.0"
8223
  }
8224
  },
 
 
 
 
 
 
8225
  "react-is": {
8226
  "version": "16.13.1",
8227
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-is/-/react-is-16.13.1.tgz",
8228
  "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
8229
  "dev": true
8230
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8231
  "reflect.getprototypeof": {
8232
  "version": "1.0.10",
8233
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -8309,6 +9893,11 @@
8309
  "isarray": "^2.0.5"
8310
  }
8311
  },
 
 
 
 
 
8312
  "safe-push-apply": {
8313
  "version": "1.0.0",
8314
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
@@ -8330,6 +9919,11 @@
8330
  "is-regex": "^1.2.1"
8331
  }
8332
  },
 
 
 
 
 
8333
  "scheduler": {
8334
  "version": "0.26.0",
8335
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/scheduler/-/scheduler-0.26.0.tgz",
@@ -8378,6 +9972,11 @@
8378
  "es-object-atoms": "^1.0.0"
8379
  }
8380
  },
 
 
 
 
 
8381
  "sharp": {
8382
  "version": "0.34.3",
8383
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/sharp/-/sharp-0.34.3.tgz",
@@ -8504,6 +10103,14 @@
8504
  "internal-slot": "^1.1.0"
8505
  }
8506
  },
 
 
 
 
 
 
 
 
8507
  "string.prototype.includes": {
8508
  "version": "2.0.1",
8509
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
@@ -8611,6 +10218,11 @@
8611
  "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
8612
  "dev": true
8613
  },
 
 
 
 
 
8614
  "tailwindcss": {
8615
  "version": "4.1.11",
8616
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tailwindcss/-/tailwindcss-4.1.11.tgz",
@@ -8700,6 +10312,12 @@
8700
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tslib/-/tslib-2.8.1.tgz",
8701
  "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
8702
  },
 
 
 
 
 
 
8703
  "type-check": {
8704
  "version": "0.4.0",
8705
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/type-check/-/type-check-0.4.0.tgz",
@@ -8823,6 +10441,28 @@
8823
  "punycode": "^2.1.0"
8824
  }
8825
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8826
  "which": {
8827
  "version": "2.0.2",
8828
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/which/-/which-2.0.2.tgz",
@@ -8899,6 +10539,19 @@
8899
  "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
8900
  "dev": true
8901
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
8902
  "yallist": {
8903
  "version": "5.0.0",
8904
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/yallist/-/yallist-5.0.0.tgz",
 
10
  "dependencies": {
11
  "@ai-sdk/openai": "^2.0.0",
12
  "@ai-sdk/react": "^2.0.1",
13
+ "@hookform/resolvers": "^5.2.1",
14
+ "@radix-ui/react-checkbox": "^1.3.3",
15
+ "@radix-ui/react-dialog": "^1.1.15",
16
+ "@radix-ui/react-label": "^2.1.7",
17
+ "@radix-ui/react-scroll-area": "^1.2.10",
18
+ "@radix-ui/react-select": "^2.2.6",
19
+ "@radix-ui/react-slider": "^1.3.6",
20
+ "@radix-ui/react-slot": "^1.2.3",
21
  "ai": "^5.0.1",
22
+ "class-variance-authority": "^0.7.1",
23
+ "clsx": "^2.1.1",
24
+ "docx": "^9.5.1",
25
+ "lucide-react": "^0.539.0",
26
  "next": "15.4.5",
27
  "react": "19.1.0",
28
  "react-dom": "19.1.0",
29
+ "react-hook-form": "^7.62.0",
30
+ "tailwind-merge": "^3.3.1",
31
  "zod": "^3.25.76"
32
  },
33
  "devDependencies": {
 
39
  "eslint": "^9",
40
  "eslint-config-next": "15.4.5",
41
  "tailwindcss": "^4",
42
+ "tw-animate-css": "^1.3.7",
43
  "typescript": "^5"
44
  }
45
  },
 
317
  "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
318
  }
319
  },
320
+ "node_modules/@floating-ui/core": {
321
+ "version": "1.7.3",
322
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/core/-/core-1.7.3.tgz",
323
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
324
+ "dependencies": {
325
+ "@floating-ui/utils": "^0.2.10"
326
+ }
327
+ },
328
+ "node_modules/@floating-ui/dom": {
329
+ "version": "1.7.3",
330
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/dom/-/dom-1.7.3.tgz",
331
+ "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==",
332
+ "dependencies": {
333
+ "@floating-ui/core": "^1.7.3",
334
+ "@floating-ui/utils": "^0.2.10"
335
+ }
336
+ },
337
+ "node_modules/@floating-ui/react-dom": {
338
+ "version": "2.1.5",
339
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/react-dom/-/react-dom-2.1.5.tgz",
340
+ "integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==",
341
+ "dependencies": {
342
+ "@floating-ui/dom": "^1.7.3"
343
+ },
344
+ "peerDependencies": {
345
+ "react": ">=16.8.0",
346
+ "react-dom": ">=16.8.0"
347
+ }
348
+ },
349
+ "node_modules/@floating-ui/utils": {
350
+ "version": "0.2.10",
351
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/utils/-/utils-0.2.10.tgz",
352
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
353
+ },
354
+ "node_modules/@hookform/resolvers": {
355
+ "version": "5.2.1",
356
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@hookform/resolvers/-/resolvers-5.2.1.tgz",
357
+ "integrity": "sha512-u0+6X58gkjMcxur1wRWokA7XsiiBJ6aK17aPZxhkoYiK5J+HcTx0Vhu9ovXe6H+dVpO6cjrn2FkJTryXEMlryQ==",
358
+ "dependencies": {
359
+ "@standard-schema/utils": "^0.3.0"
360
+ },
361
+ "peerDependencies": {
362
+ "react-hook-form": "^7.55.0"
363
+ }
364
+ },
365
  "node_modules/@humanfs/core": {
366
  "version": "0.19.1",
367
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@humanfs/core/-/core-0.19.1.tgz",
 
809
  "node": ">=8.0.0"
810
  }
811
  },
812
+ "node_modules/@radix-ui/number": {
813
+ "version": "1.1.1",
814
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/number/-/number-1.1.1.tgz",
815
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="
816
+ },
817
+ "node_modules/@radix-ui/primitive": {
818
+ "version": "1.1.3",
819
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/primitive/-/primitive-1.1.3.tgz",
820
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="
821
+ },
822
+ "node_modules/@radix-ui/react-arrow": {
823
+ "version": "1.1.7",
824
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
825
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
826
+ "dependencies": {
827
+ "@radix-ui/react-primitive": "2.1.3"
828
+ },
829
+ "peerDependencies": {
830
+ "@types/react": "*",
831
+ "@types/react-dom": "*",
832
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
833
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
834
+ },
835
+ "peerDependenciesMeta": {
836
+ "@types/react": {
837
+ "optional": true
838
+ },
839
+ "@types/react-dom": {
840
+ "optional": true
841
+ }
842
+ }
843
+ },
844
+ "node_modules/@radix-ui/react-checkbox": {
845
+ "version": "1.3.3",
846
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
847
+ "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
848
+ "dependencies": {
849
+ "@radix-ui/primitive": "1.1.3",
850
+ "@radix-ui/react-compose-refs": "1.1.2",
851
+ "@radix-ui/react-context": "1.1.2",
852
+ "@radix-ui/react-presence": "1.1.5",
853
+ "@radix-ui/react-primitive": "2.1.3",
854
+ "@radix-ui/react-use-controllable-state": "1.2.2",
855
+ "@radix-ui/react-use-previous": "1.1.1",
856
+ "@radix-ui/react-use-size": "1.1.1"
857
+ },
858
+ "peerDependencies": {
859
+ "@types/react": "*",
860
+ "@types/react-dom": "*",
861
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
862
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
863
+ },
864
+ "peerDependenciesMeta": {
865
+ "@types/react": {
866
+ "optional": true
867
+ },
868
+ "@types/react-dom": {
869
+ "optional": true
870
+ }
871
+ }
872
+ },
873
+ "node_modules/@radix-ui/react-collection": {
874
+ "version": "1.1.7",
875
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
876
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
877
+ "dependencies": {
878
+ "@radix-ui/react-compose-refs": "1.1.2",
879
+ "@radix-ui/react-context": "1.1.2",
880
+ "@radix-ui/react-primitive": "2.1.3",
881
+ "@radix-ui/react-slot": "1.2.3"
882
+ },
883
+ "peerDependencies": {
884
+ "@types/react": "*",
885
+ "@types/react-dom": "*",
886
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
887
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
888
+ },
889
+ "peerDependenciesMeta": {
890
+ "@types/react": {
891
+ "optional": true
892
+ },
893
+ "@types/react-dom": {
894
+ "optional": true
895
+ }
896
+ }
897
+ },
898
+ "node_modules/@radix-ui/react-compose-refs": {
899
+ "version": "1.1.2",
900
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
901
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
902
+ "peerDependencies": {
903
+ "@types/react": "*",
904
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
905
+ },
906
+ "peerDependenciesMeta": {
907
+ "@types/react": {
908
+ "optional": true
909
+ }
910
+ }
911
+ },
912
+ "node_modules/@radix-ui/react-context": {
913
+ "version": "1.1.2",
914
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-context/-/react-context-1.1.2.tgz",
915
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
916
+ "peerDependencies": {
917
+ "@types/react": "*",
918
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
919
+ },
920
+ "peerDependenciesMeta": {
921
+ "@types/react": {
922
+ "optional": true
923
+ }
924
+ }
925
+ },
926
+ "node_modules/@radix-ui/react-dialog": {
927
+ "version": "1.1.15",
928
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
929
+ "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
930
+ "dependencies": {
931
+ "@radix-ui/primitive": "1.1.3",
932
+ "@radix-ui/react-compose-refs": "1.1.2",
933
+ "@radix-ui/react-context": "1.1.2",
934
+ "@radix-ui/react-dismissable-layer": "1.1.11",
935
+ "@radix-ui/react-focus-guards": "1.1.3",
936
+ "@radix-ui/react-focus-scope": "1.1.7",
937
+ "@radix-ui/react-id": "1.1.1",
938
+ "@radix-ui/react-portal": "1.1.9",
939
+ "@radix-ui/react-presence": "1.1.5",
940
+ "@radix-ui/react-primitive": "2.1.3",
941
+ "@radix-ui/react-slot": "1.2.3",
942
+ "@radix-ui/react-use-controllable-state": "1.2.2",
943
+ "aria-hidden": "^1.2.4",
944
+ "react-remove-scroll": "^2.6.3"
945
+ },
946
+ "peerDependencies": {
947
+ "@types/react": "*",
948
+ "@types/react-dom": "*",
949
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
950
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
951
+ },
952
+ "peerDependenciesMeta": {
953
+ "@types/react": {
954
+ "optional": true
955
+ },
956
+ "@types/react-dom": {
957
+ "optional": true
958
+ }
959
+ }
960
+ },
961
+ "node_modules/@radix-ui/react-direction": {
962
+ "version": "1.1.1",
963
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
964
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
965
+ "peerDependencies": {
966
+ "@types/react": "*",
967
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
968
+ },
969
+ "peerDependenciesMeta": {
970
+ "@types/react": {
971
+ "optional": true
972
+ }
973
+ }
974
+ },
975
+ "node_modules/@radix-ui/react-dismissable-layer": {
976
+ "version": "1.1.11",
977
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
978
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
979
+ "dependencies": {
980
+ "@radix-ui/primitive": "1.1.3",
981
+ "@radix-ui/react-compose-refs": "1.1.2",
982
+ "@radix-ui/react-primitive": "2.1.3",
983
+ "@radix-ui/react-use-callback-ref": "1.1.1",
984
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
985
+ },
986
+ "peerDependencies": {
987
+ "@types/react": "*",
988
+ "@types/react-dom": "*",
989
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
990
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
991
+ },
992
+ "peerDependenciesMeta": {
993
+ "@types/react": {
994
+ "optional": true
995
+ },
996
+ "@types/react-dom": {
997
+ "optional": true
998
+ }
999
+ }
1000
+ },
1001
+ "node_modules/@radix-ui/react-focus-guards": {
1002
+ "version": "1.1.3",
1003
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
1004
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
1005
+ "peerDependencies": {
1006
+ "@types/react": "*",
1007
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1008
+ },
1009
+ "peerDependenciesMeta": {
1010
+ "@types/react": {
1011
+ "optional": true
1012
+ }
1013
+ }
1014
+ },
1015
+ "node_modules/@radix-ui/react-focus-scope": {
1016
+ "version": "1.1.7",
1017
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
1018
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
1019
+ "dependencies": {
1020
+ "@radix-ui/react-compose-refs": "1.1.2",
1021
+ "@radix-ui/react-primitive": "2.1.3",
1022
+ "@radix-ui/react-use-callback-ref": "1.1.1"
1023
+ },
1024
+ "peerDependencies": {
1025
+ "@types/react": "*",
1026
+ "@types/react-dom": "*",
1027
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1028
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1029
+ },
1030
+ "peerDependenciesMeta": {
1031
+ "@types/react": {
1032
+ "optional": true
1033
+ },
1034
+ "@types/react-dom": {
1035
+ "optional": true
1036
+ }
1037
+ }
1038
+ },
1039
+ "node_modules/@radix-ui/react-id": {
1040
+ "version": "1.1.1",
1041
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-id/-/react-id-1.1.1.tgz",
1042
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
1043
+ "dependencies": {
1044
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1045
+ },
1046
+ "peerDependencies": {
1047
+ "@types/react": "*",
1048
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1049
+ },
1050
+ "peerDependenciesMeta": {
1051
+ "@types/react": {
1052
+ "optional": true
1053
+ }
1054
+ }
1055
+ },
1056
+ "node_modules/@radix-ui/react-label": {
1057
+ "version": "2.1.7",
1058
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-label/-/react-label-2.1.7.tgz",
1059
+ "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==",
1060
+ "dependencies": {
1061
+ "@radix-ui/react-primitive": "2.1.3"
1062
+ },
1063
+ "peerDependencies": {
1064
+ "@types/react": "*",
1065
+ "@types/react-dom": "*",
1066
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1067
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1068
+ },
1069
+ "peerDependenciesMeta": {
1070
+ "@types/react": {
1071
+ "optional": true
1072
+ },
1073
+ "@types/react-dom": {
1074
+ "optional": true
1075
+ }
1076
+ }
1077
+ },
1078
+ "node_modules/@radix-ui/react-popper": {
1079
+ "version": "1.2.8",
1080
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
1081
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
1082
+ "dependencies": {
1083
+ "@floating-ui/react-dom": "^2.0.0",
1084
+ "@radix-ui/react-arrow": "1.1.7",
1085
+ "@radix-ui/react-compose-refs": "1.1.2",
1086
+ "@radix-ui/react-context": "1.1.2",
1087
+ "@radix-ui/react-primitive": "2.1.3",
1088
+ "@radix-ui/react-use-callback-ref": "1.1.1",
1089
+ "@radix-ui/react-use-layout-effect": "1.1.1",
1090
+ "@radix-ui/react-use-rect": "1.1.1",
1091
+ "@radix-ui/react-use-size": "1.1.1",
1092
+ "@radix-ui/rect": "1.1.1"
1093
+ },
1094
+ "peerDependencies": {
1095
+ "@types/react": "*",
1096
+ "@types/react-dom": "*",
1097
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1098
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1099
+ },
1100
+ "peerDependenciesMeta": {
1101
+ "@types/react": {
1102
+ "optional": true
1103
+ },
1104
+ "@types/react-dom": {
1105
+ "optional": true
1106
+ }
1107
+ }
1108
+ },
1109
+ "node_modules/@radix-ui/react-portal": {
1110
+ "version": "1.1.9",
1111
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
1112
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
1113
+ "dependencies": {
1114
+ "@radix-ui/react-primitive": "2.1.3",
1115
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1116
+ },
1117
+ "peerDependencies": {
1118
+ "@types/react": "*",
1119
+ "@types/react-dom": "*",
1120
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1121
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1122
+ },
1123
+ "peerDependenciesMeta": {
1124
+ "@types/react": {
1125
+ "optional": true
1126
+ },
1127
+ "@types/react-dom": {
1128
+ "optional": true
1129
+ }
1130
+ }
1131
+ },
1132
+ "node_modules/@radix-ui/react-presence": {
1133
+ "version": "1.1.5",
1134
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
1135
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
1136
+ "dependencies": {
1137
+ "@radix-ui/react-compose-refs": "1.1.2",
1138
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1139
+ },
1140
+ "peerDependencies": {
1141
+ "@types/react": "*",
1142
+ "@types/react-dom": "*",
1143
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1144
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1145
+ },
1146
+ "peerDependenciesMeta": {
1147
+ "@types/react": {
1148
+ "optional": true
1149
+ },
1150
+ "@types/react-dom": {
1151
+ "optional": true
1152
+ }
1153
+ }
1154
+ },
1155
+ "node_modules/@radix-ui/react-primitive": {
1156
+ "version": "2.1.3",
1157
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
1158
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
1159
+ "dependencies": {
1160
+ "@radix-ui/react-slot": "1.2.3"
1161
+ },
1162
+ "peerDependencies": {
1163
+ "@types/react": "*",
1164
+ "@types/react-dom": "*",
1165
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1166
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1167
+ },
1168
+ "peerDependenciesMeta": {
1169
+ "@types/react": {
1170
+ "optional": true
1171
+ },
1172
+ "@types/react-dom": {
1173
+ "optional": true
1174
+ }
1175
+ }
1176
+ },
1177
+ "node_modules/@radix-ui/react-scroll-area": {
1178
+ "version": "1.2.10",
1179
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz",
1180
+ "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==",
1181
+ "dependencies": {
1182
+ "@radix-ui/number": "1.1.1",
1183
+ "@radix-ui/primitive": "1.1.3",
1184
+ "@radix-ui/react-compose-refs": "1.1.2",
1185
+ "@radix-ui/react-context": "1.1.2",
1186
+ "@radix-ui/react-direction": "1.1.1",
1187
+ "@radix-ui/react-presence": "1.1.5",
1188
+ "@radix-ui/react-primitive": "2.1.3",
1189
+ "@radix-ui/react-use-callback-ref": "1.1.1",
1190
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1191
+ },
1192
+ "peerDependencies": {
1193
+ "@types/react": "*",
1194
+ "@types/react-dom": "*",
1195
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1196
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1197
+ },
1198
+ "peerDependenciesMeta": {
1199
+ "@types/react": {
1200
+ "optional": true
1201
+ },
1202
+ "@types/react-dom": {
1203
+ "optional": true
1204
+ }
1205
+ }
1206
+ },
1207
+ "node_modules/@radix-ui/react-select": {
1208
+ "version": "2.2.6",
1209
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-select/-/react-select-2.2.6.tgz",
1210
+ "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
1211
+ "dependencies": {
1212
+ "@radix-ui/number": "1.1.1",
1213
+ "@radix-ui/primitive": "1.1.3",
1214
+ "@radix-ui/react-collection": "1.1.7",
1215
+ "@radix-ui/react-compose-refs": "1.1.2",
1216
+ "@radix-ui/react-context": "1.1.2",
1217
+ "@radix-ui/react-direction": "1.1.1",
1218
+ "@radix-ui/react-dismissable-layer": "1.1.11",
1219
+ "@radix-ui/react-focus-guards": "1.1.3",
1220
+ "@radix-ui/react-focus-scope": "1.1.7",
1221
+ "@radix-ui/react-id": "1.1.1",
1222
+ "@radix-ui/react-popper": "1.2.8",
1223
+ "@radix-ui/react-portal": "1.1.9",
1224
+ "@radix-ui/react-primitive": "2.1.3",
1225
+ "@radix-ui/react-slot": "1.2.3",
1226
+ "@radix-ui/react-use-callback-ref": "1.1.1",
1227
+ "@radix-ui/react-use-controllable-state": "1.2.2",
1228
+ "@radix-ui/react-use-layout-effect": "1.1.1",
1229
+ "@radix-ui/react-use-previous": "1.1.1",
1230
+ "@radix-ui/react-visually-hidden": "1.2.3",
1231
+ "aria-hidden": "^1.2.4",
1232
+ "react-remove-scroll": "^2.6.3"
1233
+ },
1234
+ "peerDependencies": {
1235
+ "@types/react": "*",
1236
+ "@types/react-dom": "*",
1237
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1238
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1239
+ },
1240
+ "peerDependenciesMeta": {
1241
+ "@types/react": {
1242
+ "optional": true
1243
+ },
1244
+ "@types/react-dom": {
1245
+ "optional": true
1246
+ }
1247
+ }
1248
+ },
1249
+ "node_modules/@radix-ui/react-slider": {
1250
+ "version": "1.3.6",
1251
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-slider/-/react-slider-1.3.6.tgz",
1252
+ "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==",
1253
+ "dependencies": {
1254
+ "@radix-ui/number": "1.1.1",
1255
+ "@radix-ui/primitive": "1.1.3",
1256
+ "@radix-ui/react-collection": "1.1.7",
1257
+ "@radix-ui/react-compose-refs": "1.1.2",
1258
+ "@radix-ui/react-context": "1.1.2",
1259
+ "@radix-ui/react-direction": "1.1.1",
1260
+ "@radix-ui/react-primitive": "2.1.3",
1261
+ "@radix-ui/react-use-controllable-state": "1.2.2",
1262
+ "@radix-ui/react-use-layout-effect": "1.1.1",
1263
+ "@radix-ui/react-use-previous": "1.1.1",
1264
+ "@radix-ui/react-use-size": "1.1.1"
1265
+ },
1266
+ "peerDependencies": {
1267
+ "@types/react": "*",
1268
+ "@types/react-dom": "*",
1269
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1270
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1271
+ },
1272
+ "peerDependenciesMeta": {
1273
+ "@types/react": {
1274
+ "optional": true
1275
+ },
1276
+ "@types/react-dom": {
1277
+ "optional": true
1278
+ }
1279
+ }
1280
+ },
1281
+ "node_modules/@radix-ui/react-slot": {
1282
+ "version": "1.2.3",
1283
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
1284
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
1285
+ "dependencies": {
1286
+ "@radix-ui/react-compose-refs": "1.1.2"
1287
+ },
1288
+ "peerDependencies": {
1289
+ "@types/react": "*",
1290
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1291
+ },
1292
+ "peerDependenciesMeta": {
1293
+ "@types/react": {
1294
+ "optional": true
1295
+ }
1296
+ }
1297
+ },
1298
+ "node_modules/@radix-ui/react-use-callback-ref": {
1299
+ "version": "1.1.1",
1300
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
1301
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
1302
+ "peerDependencies": {
1303
+ "@types/react": "*",
1304
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1305
+ },
1306
+ "peerDependenciesMeta": {
1307
+ "@types/react": {
1308
+ "optional": true
1309
+ }
1310
+ }
1311
+ },
1312
+ "node_modules/@radix-ui/react-use-controllable-state": {
1313
+ "version": "1.2.2",
1314
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
1315
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
1316
+ "dependencies": {
1317
+ "@radix-ui/react-use-effect-event": "0.0.2",
1318
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1319
+ },
1320
+ "peerDependencies": {
1321
+ "@types/react": "*",
1322
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1323
+ },
1324
+ "peerDependenciesMeta": {
1325
+ "@types/react": {
1326
+ "optional": true
1327
+ }
1328
+ }
1329
+ },
1330
+ "node_modules/@radix-ui/react-use-effect-event": {
1331
+ "version": "0.0.2",
1332
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
1333
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
1334
+ "dependencies": {
1335
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1336
+ },
1337
+ "peerDependencies": {
1338
+ "@types/react": "*",
1339
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1340
+ },
1341
+ "peerDependenciesMeta": {
1342
+ "@types/react": {
1343
+ "optional": true
1344
+ }
1345
+ }
1346
+ },
1347
+ "node_modules/@radix-ui/react-use-escape-keydown": {
1348
+ "version": "1.1.1",
1349
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
1350
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
1351
+ "dependencies": {
1352
+ "@radix-ui/react-use-callback-ref": "1.1.1"
1353
+ },
1354
+ "peerDependencies": {
1355
+ "@types/react": "*",
1356
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1357
+ },
1358
+ "peerDependenciesMeta": {
1359
+ "@types/react": {
1360
+ "optional": true
1361
+ }
1362
+ }
1363
+ },
1364
+ "node_modules/@radix-ui/react-use-layout-effect": {
1365
+ "version": "1.1.1",
1366
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
1367
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
1368
+ "peerDependencies": {
1369
+ "@types/react": "*",
1370
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1371
+ },
1372
+ "peerDependenciesMeta": {
1373
+ "@types/react": {
1374
+ "optional": true
1375
+ }
1376
+ }
1377
+ },
1378
+ "node_modules/@radix-ui/react-use-previous": {
1379
+ "version": "1.1.1",
1380
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
1381
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
1382
+ "peerDependencies": {
1383
+ "@types/react": "*",
1384
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1385
+ },
1386
+ "peerDependenciesMeta": {
1387
+ "@types/react": {
1388
+ "optional": true
1389
+ }
1390
+ }
1391
+ },
1392
+ "node_modules/@radix-ui/react-use-rect": {
1393
+ "version": "1.1.1",
1394
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
1395
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
1396
+ "dependencies": {
1397
+ "@radix-ui/rect": "1.1.1"
1398
+ },
1399
+ "peerDependencies": {
1400
+ "@types/react": "*",
1401
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1402
+ },
1403
+ "peerDependenciesMeta": {
1404
+ "@types/react": {
1405
+ "optional": true
1406
+ }
1407
+ }
1408
+ },
1409
+ "node_modules/@radix-ui/react-use-size": {
1410
+ "version": "1.1.1",
1411
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
1412
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
1413
+ "dependencies": {
1414
+ "@radix-ui/react-use-layout-effect": "1.1.1"
1415
+ },
1416
+ "peerDependencies": {
1417
+ "@types/react": "*",
1418
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1419
+ },
1420
+ "peerDependenciesMeta": {
1421
+ "@types/react": {
1422
+ "optional": true
1423
+ }
1424
+ }
1425
+ },
1426
+ "node_modules/@radix-ui/react-visually-hidden": {
1427
+ "version": "1.2.3",
1428
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
1429
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
1430
+ "dependencies": {
1431
+ "@radix-ui/react-primitive": "2.1.3"
1432
+ },
1433
+ "peerDependencies": {
1434
+ "@types/react": "*",
1435
+ "@types/react-dom": "*",
1436
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
1437
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
1438
+ },
1439
+ "peerDependenciesMeta": {
1440
+ "@types/react": {
1441
+ "optional": true
1442
+ },
1443
+ "@types/react-dom": {
1444
+ "optional": true
1445
+ }
1446
+ }
1447
+ },
1448
+ "node_modules/@radix-ui/rect": {
1449
+ "version": "1.1.1",
1450
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/rect/-/rect-1.1.1.tgz",
1451
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="
1452
+ },
1453
  "node_modules/@rtsao/scc": {
1454
  "version": "1.1.0",
1455
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@rtsao/scc/-/scc-1.1.0.tgz",
 
1467
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@standard-schema/spec/-/spec-1.0.0.tgz",
1468
  "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="
1469
  },
1470
+ "node_modules/@standard-schema/utils": {
1471
+ "version": "0.3.0",
1472
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@standard-schema/utils/-/utils-0.3.0.tgz",
1473
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="
1474
+ },
1475
  "node_modules/@swc/helpers": {
1476
  "version": "0.5.15",
1477
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@swc/helpers/-/helpers-0.5.15.tgz",
 
1773
  "version": "19.1.9",
1774
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react/-/react-19.1.9.tgz",
1775
  "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==",
1776
+ "devOptional": true,
1777
  "dependencies": {
1778
  "csstype": "^3.0.2"
1779
  }
 
1782
  "version": "19.1.7",
1783
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react-dom/-/react-dom-19.1.7.tgz",
1784
  "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
1785
+ "devOptional": true,
1786
  "peerDependencies": {
1787
  "@types/react": "^19.0.0"
1788
  }
 
2256
  "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
2257
  "dev": true
2258
  },
2259
+ "node_modules/aria-hidden": {
2260
+ "version": "1.2.6",
2261
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/aria-hidden/-/aria-hidden-1.2.6.tgz",
2262
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
2263
+ "dependencies": {
2264
+ "tslib": "^2.0.0"
2265
+ },
2266
+ "engines": {
2267
+ "node": ">=10"
2268
+ }
2269
+ },
2270
  "node_modules/aria-query": {
2271
  "version": "5.3.2",
2272
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/aria-query/-/aria-query-5.3.2.tgz",
 
2557
  "node": ">=18"
2558
  }
2559
  },
2560
+ "node_modules/class-variance-authority": {
2561
+ "version": "0.7.1",
2562
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
2563
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
2564
+ "dependencies": {
2565
+ "clsx": "^2.1.1"
2566
+ }
2567
+ },
2568
  "node_modules/client-only": {
2569
  "version": "0.0.1",
2570
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/client-only/-/client-only-0.0.1.tgz",
2571
  "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
2572
  },
2573
+ "node_modules/clsx": {
2574
+ "version": "2.1.1",
2575
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/clsx/-/clsx-2.1.1.tgz",
2576
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
2577
+ "engines": {
2578
+ "node": ">=6"
2579
+ }
2580
+ },
2581
  "node_modules/color": {
2582
  "version": "4.2.3",
2583
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/color/-/color-4.2.3.tgz",
 
2625
  "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
2626
  "dev": true
2627
  },
2628
+ "node_modules/core-util-is": {
2629
+ "version": "1.0.3",
2630
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/core-util-is/-/core-util-is-1.0.3.tgz",
2631
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
2632
+ },
2633
  "node_modules/cross-spawn": {
2634
  "version": "7.0.6",
2635
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/cross-spawn/-/cross-spawn-7.0.6.tgz",
 
2648
  "version": "3.1.3",
2649
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/csstype/-/csstype-3.1.3.tgz",
2650
  "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
2651
+ "devOptional": true
2652
  },
2653
  "node_modules/damerau-levenshtein": {
2654
  "version": "1.0.8",
 
2766
  "node": ">=8"
2767
  }
2768
  },
2769
+ "node_modules/detect-node-es": {
2770
+ "version": "1.1.0",
2771
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/detect-node-es/-/detect-node-es-1.1.0.tgz",
2772
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
2773
+ },
2774
  "node_modules/doctrine": {
2775
  "version": "2.1.0",
2776
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/doctrine/-/doctrine-2.1.0.tgz",
 
2783
  "node": ">=0.10.0"
2784
  }
2785
  },
2786
+ "node_modules/docx": {
2787
+ "version": "9.5.1",
2788
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/docx/-/docx-9.5.1.tgz",
2789
+ "integrity": "sha512-ABDI7JEirFD2+bHhOBlsGZxaG1UgZb2M/QMKhLSDGgVNhxDesTCDcP+qoDnDGjZ4EOXTRfUjUgwHVuZ6VSTfWQ==",
2790
+ "dependencies": {
2791
+ "@types/node": "^24.0.1",
2792
+ "hash.js": "^1.1.7",
2793
+ "jszip": "^3.10.1",
2794
+ "nanoid": "^5.1.3",
2795
+ "xml": "^1.0.1",
2796
+ "xml-js": "^1.6.8"
2797
+ },
2798
+ "engines": {
2799
+ "node": ">=10"
2800
+ }
2801
+ },
2802
+ "node_modules/docx/node_modules/@types/node": {
2803
+ "version": "24.3.0",
2804
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/node/-/node-24.3.0.tgz",
2805
+ "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
2806
+ "dependencies": {
2807
+ "undici-types": "~7.10.0"
2808
+ }
2809
+ },
2810
+ "node_modules/docx/node_modules/nanoid": {
2811
+ "version": "5.1.5",
2812
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/nanoid/-/nanoid-5.1.5.tgz",
2813
+ "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
2814
+ "bin": {
2815
+ "nanoid": "bin/nanoid.js"
2816
+ },
2817
+ "engines": {
2818
+ "node": "^18 || >=20"
2819
+ }
2820
+ },
2821
+ "node_modules/docx/node_modules/undici-types": {
2822
+ "version": "7.10.0",
2823
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/undici-types/-/undici-types-7.10.0.tgz",
2824
+ "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="
2825
+ },
2826
  "node_modules/dunder-proto": {
2827
  "version": "1.0.1",
2828
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/dunder-proto/-/dunder-proto-1.0.1.tgz",
 
3595
  "node": ">= 0.4"
3596
  }
3597
  },
3598
+ "node_modules/get-nonce": {
3599
+ "version": "1.0.1",
3600
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/get-nonce/-/get-nonce-1.0.1.tgz",
3601
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
3602
+ "engines": {
3603
+ "node": ">=6"
3604
+ }
3605
+ },
3606
  "node_modules/get-proto": {
3607
  "version": "1.0.1",
3608
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/get-proto/-/get-proto-1.0.1.tgz",
 
3754
  "node": ">= 0.4"
3755
  }
3756
  },
3757
+ "node_modules/hash.js": {
3758
+ "version": "1.1.7",
3759
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/hash.js/-/hash.js-1.1.7.tgz",
3760
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
3761
+ "dependencies": {
3762
+ "inherits": "^2.0.3",
3763
+ "minimalistic-assert": "^1.0.1"
3764
+ }
3765
+ },
3766
  "node_modules/hasown": {
3767
  "version": "2.0.2",
3768
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/hasown/-/hasown-2.0.2.tgz",
 
3784
  "node": ">= 4"
3785
  }
3786
  },
3787
+ "node_modules/immediate": {
3788
+ "version": "3.0.6",
3789
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/immediate/-/immediate-3.0.6.tgz",
3790
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
3791
+ },
3792
  "node_modules/import-fresh": {
3793
  "version": "3.3.1",
3794
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/import-fresh/-/import-fresh-3.3.1.tgz",
 
3811
  "node": ">=0.8.19"
3812
  }
3813
  },
3814
+ "node_modules/inherits": {
3815
+ "version": "2.0.4",
3816
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/inherits/-/inherits-2.0.4.tgz",
3817
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
3818
+ },
3819
  "node_modules/internal-slot": {
3820
  "version": "1.1.0",
3821
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/internal-slot/-/internal-slot-1.1.0.tgz",
 
4251
  "node": ">=4.0"
4252
  }
4253
  },
4254
+ "node_modules/jszip": {
4255
+ "version": "3.10.1",
4256
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/jszip/-/jszip-3.10.1.tgz",
4257
+ "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
4258
+ "dependencies": {
4259
+ "lie": "~3.3.0",
4260
+ "pako": "~1.0.2",
4261
+ "readable-stream": "~2.3.6",
4262
+ "setimmediate": "^1.0.5"
4263
+ }
4264
+ },
4265
  "node_modules/keyv": {
4266
  "version": "4.5.4",
4267
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/keyv/-/keyv-4.5.4.tgz",
 
4302
  "node": ">= 0.8.0"
4303
  }
4304
  },
4305
+ "node_modules/lie": {
4306
+ "version": "3.3.0",
4307
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lie/-/lie-3.3.0.tgz",
4308
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
4309
+ "dependencies": {
4310
+ "immediate": "~3.0.5"
4311
+ }
4312
+ },
4313
  "node_modules/lightningcss": {
4314
  "version": "1.30.1",
4315
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lightningcss/-/lightningcss-1.30.1.tgz",
 
4464
  "loose-envify": "cli.js"
4465
  }
4466
  },
4467
+ "node_modules/lucide-react": {
4468
+ "version": "0.539.0",
4469
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lucide-react/-/lucide-react-0.539.0.tgz",
4470
+ "integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg==",
4471
+ "peerDependencies": {
4472
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
4473
+ }
4474
+ },
4475
  "node_modules/magic-string": {
4476
  "version": "0.30.17",
4477
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/magic-string/-/magic-string-0.30.17.tgz",
 
4512
  "node": ">=8.6"
4513
  }
4514
  },
4515
+ "node_modules/minimalistic-assert": {
4516
+ "version": "1.0.1",
4517
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
4518
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
4519
+ },
4520
  "node_modules/minimatch": {
4521
  "version": "3.1.2",
4522
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/minimatch/-/minimatch-3.1.2.tgz",
 
4847
  "node": ">=10"
4848
  }
4849
  },
4850
+ "node_modules/pako": {
4851
+ "version": "1.0.11",
4852
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/pako/-/pako-1.0.11.tgz",
4853
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
4854
+ },
4855
  "node_modules/parent-module": {
4856
  "version": "1.0.1",
4857
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/parent-module/-/parent-module-1.0.1.tgz",
 
4934
  "node": ">= 0.8.0"
4935
  }
4936
  },
4937
+ "node_modules/process-nextick-args": {
4938
+ "version": "2.0.1",
4939
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
4940
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
4941
+ },
4942
  "node_modules/prop-types": {
4943
  "version": "15.8.1",
4944
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/prop-types/-/prop-types-15.8.1.tgz",
 
4984
  "react": "^19.1.0"
4985
  }
4986
  },
4987
+ "node_modules/react-hook-form": {
4988
+ "version": "7.62.0",
4989
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-hook-form/-/react-hook-form-7.62.0.tgz",
4990
+ "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==",
4991
+ "engines": {
4992
+ "node": ">=18.0.0"
4993
+ },
4994
+ "peerDependencies": {
4995
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
4996
+ }
4997
+ },
4998
  "node_modules/react-is": {
4999
  "version": "16.13.1",
5000
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-is/-/react-is-16.13.1.tgz",
5001
  "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
5002
  "dev": true
5003
  },
5004
+ "node_modules/react-remove-scroll": {
5005
+ "version": "2.7.1",
5006
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
5007
+ "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
5008
+ "dependencies": {
5009
+ "react-remove-scroll-bar": "^2.3.7",
5010
+ "react-style-singleton": "^2.2.3",
5011
+ "tslib": "^2.1.0",
5012
+ "use-callback-ref": "^1.3.3",
5013
+ "use-sidecar": "^1.1.3"
5014
+ },
5015
+ "engines": {
5016
+ "node": ">=10"
5017
+ },
5018
+ "peerDependencies": {
5019
+ "@types/react": "*",
5020
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
5021
+ },
5022
+ "peerDependenciesMeta": {
5023
+ "@types/react": {
5024
+ "optional": true
5025
+ }
5026
+ }
5027
+ },
5028
+ "node_modules/react-remove-scroll-bar": {
5029
+ "version": "2.3.8",
5030
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
5031
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
5032
+ "dependencies": {
5033
+ "react-style-singleton": "^2.2.2",
5034
+ "tslib": "^2.0.0"
5035
+ },
5036
+ "engines": {
5037
+ "node": ">=10"
5038
+ },
5039
+ "peerDependencies": {
5040
+ "@types/react": "*",
5041
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
5042
+ },
5043
+ "peerDependenciesMeta": {
5044
+ "@types/react": {
5045
+ "optional": true
5046
+ }
5047
+ }
5048
+ },
5049
+ "node_modules/react-style-singleton": {
5050
+ "version": "2.2.3",
5051
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
5052
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
5053
+ "dependencies": {
5054
+ "get-nonce": "^1.0.0",
5055
+ "tslib": "^2.0.0"
5056
+ },
5057
+ "engines": {
5058
+ "node": ">=10"
5059
+ },
5060
+ "peerDependencies": {
5061
+ "@types/react": "*",
5062
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
5063
+ },
5064
+ "peerDependenciesMeta": {
5065
+ "@types/react": {
5066
+ "optional": true
5067
+ }
5068
+ }
5069
+ },
5070
+ "node_modules/readable-stream": {
5071
+ "version": "2.3.8",
5072
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/readable-stream/-/readable-stream-2.3.8.tgz",
5073
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
5074
+ "dependencies": {
5075
+ "core-util-is": "~1.0.0",
5076
+ "inherits": "~2.0.3",
5077
+ "isarray": "~1.0.0",
5078
+ "process-nextick-args": "~2.0.0",
5079
+ "safe-buffer": "~5.1.1",
5080
+ "string_decoder": "~1.1.1",
5081
+ "util-deprecate": "~1.0.1"
5082
+ }
5083
+ },
5084
+ "node_modules/readable-stream/node_modules/isarray": {
5085
+ "version": "1.0.0",
5086
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/isarray/-/isarray-1.0.0.tgz",
5087
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
5088
+ },
5089
  "node_modules/reflect.getprototypeof": {
5090
  "version": "1.0.10",
5091
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
 
5189
  "node": ">=0.4"
5190
  }
5191
  },
5192
+ "node_modules/safe-buffer": {
5193
+ "version": "5.1.2",
5194
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/safe-buffer/-/safe-buffer-5.1.2.tgz",
5195
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
5196
+ },
5197
  "node_modules/safe-push-apply": {
5198
  "version": "1.0.0",
5199
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
 
5221
  "node": ">= 0.4"
5222
  }
5223
  },
5224
+ "node_modules/sax": {
5225
+ "version": "1.4.1",
5226
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/sax/-/sax-1.4.1.tgz",
5227
+ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
5228
+ },
5229
  "node_modules/scheduler": {
5230
  "version": "0.26.0",
5231
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/scheduler/-/scheduler-0.26.0.tgz",
 
5289
  "node": ">= 0.4"
5290
  }
5291
  },
5292
+ "node_modules/setimmediate": {
5293
+ "version": "1.0.5",
5294
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/setimmediate/-/setimmediate-1.0.5.tgz",
5295
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
5296
+ },
5297
  "node_modules/sharp": {
5298
  "version": "0.34.3",
5299
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/sharp/-/sharp-0.34.3.tgz",
 
5450
  "node": ">= 0.4"
5451
  }
5452
  },
5453
+ "node_modules/string_decoder": {
5454
+ "version": "1.1.1",
5455
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/string_decoder/-/string_decoder-1.1.1.tgz",
5456
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
5457
+ "dependencies": {
5458
+ "safe-buffer": "~5.1.0"
5459
+ }
5460
+ },
5461
  "node_modules/string.prototype.includes": {
5462
  "version": "2.0.1",
5463
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
 
5592
  "node": ">= 0.4"
5593
  }
5594
  },
5595
+ "node_modules/tailwind-merge": {
5596
+ "version": "3.3.1",
5597
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
5598
+ "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="
5599
+ },
5600
  "node_modules/tailwindcss": {
5601
  "version": "4.1.11",
5602
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tailwindcss/-/tailwindcss-4.1.11.tgz",
 
5714
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tslib/-/tslib-2.8.1.tgz",
5715
  "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
5716
  },
5717
+ "node_modules/tw-animate-css": {
5718
+ "version": "1.3.7",
5719
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tw-animate-css/-/tw-animate-css-1.3.7.tgz",
5720
+ "integrity": "sha512-lvLb3hTIpB5oGsk8JmLoAjeCHV58nKa2zHYn8yWOoG5JJusH3bhJlF2DLAZ/5NmJ+jyH3ssiAx/2KmbhavJy/A==",
5721
+ "dev": true
5722
+ },
5723
  "node_modules/type-check": {
5724
  "version": "0.4.0",
5725
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/type-check/-/type-check-0.4.0.tgz",
 
5871
  "punycode": "^2.1.0"
5872
  }
5873
  },
5874
+ "node_modules/use-callback-ref": {
5875
+ "version": "1.3.3",
5876
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
5877
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
5878
+ "dependencies": {
5879
+ "tslib": "^2.0.0"
5880
+ },
5881
+ "engines": {
5882
+ "node": ">=10"
5883
+ },
5884
+ "peerDependencies": {
5885
+ "@types/react": "*",
5886
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
5887
+ },
5888
+ "peerDependenciesMeta": {
5889
+ "@types/react": {
5890
+ "optional": true
5891
+ }
5892
+ }
5893
+ },
5894
+ "node_modules/use-sidecar": {
5895
+ "version": "1.1.3",
5896
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/use-sidecar/-/use-sidecar-1.1.3.tgz",
5897
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
5898
+ "dependencies": {
5899
+ "detect-node-es": "^1.1.0",
5900
+ "tslib": "^2.0.0"
5901
+ },
5902
+ "engines": {
5903
+ "node": ">=10"
5904
+ },
5905
+ "peerDependencies": {
5906
+ "@types/react": "*",
5907
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
5908
+ },
5909
+ "peerDependenciesMeta": {
5910
+ "@types/react": {
5911
+ "optional": true
5912
+ }
5913
+ }
5914
+ },
5915
+ "node_modules/util-deprecate": {
5916
+ "version": "1.0.2",
5917
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/util-deprecate/-/util-deprecate-1.0.2.tgz",
5918
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
5919
+ },
5920
  "node_modules/which": {
5921
  "version": "2.0.2",
5922
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/which/-/which-2.0.2.tgz",
 
6014
  "node": ">=0.10.0"
6015
  }
6016
  },
6017
+ "node_modules/xml": {
6018
+ "version": "1.0.1",
6019
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/xml/-/xml-1.0.1.tgz",
6020
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw=="
6021
+ },
6022
+ "node_modules/xml-js": {
6023
+ "version": "1.6.11",
6024
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/xml-js/-/xml-js-1.6.11.tgz",
6025
+ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
6026
+ "dependencies": {
6027
+ "sax": "^1.2.4"
6028
+ },
6029
+ "bin": {
6030
+ "xml-js": "bin/cli.js"
6031
+ }
6032
+ },
6033
  "node_modules/yallist": {
6034
  "version": "5.0.0",
6035
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/yallist/-/yallist-5.0.0.tgz",
 
6268
  "levn": "^0.4.1"
6269
  }
6270
  },
6271
+ "@floating-ui/core": {
6272
+ "version": "1.7.3",
6273
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/core/-/core-1.7.3.tgz",
6274
+ "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
6275
+ "requires": {
6276
+ "@floating-ui/utils": "^0.2.10"
6277
+ }
6278
+ },
6279
+ "@floating-ui/dom": {
6280
+ "version": "1.7.3",
6281
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/dom/-/dom-1.7.3.tgz",
6282
+ "integrity": "sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==",
6283
+ "requires": {
6284
+ "@floating-ui/core": "^1.7.3",
6285
+ "@floating-ui/utils": "^0.2.10"
6286
+ }
6287
+ },
6288
+ "@floating-ui/react-dom": {
6289
+ "version": "2.1.5",
6290
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/react-dom/-/react-dom-2.1.5.tgz",
6291
+ "integrity": "sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==",
6292
+ "requires": {
6293
+ "@floating-ui/dom": "^1.7.3"
6294
+ }
6295
+ },
6296
+ "@floating-ui/utils": {
6297
+ "version": "0.2.10",
6298
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@floating-ui/utils/-/utils-0.2.10.tgz",
6299
+ "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="
6300
+ },
6301
+ "@hookform/resolvers": {
6302
+ "version": "5.2.1",
6303
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@hookform/resolvers/-/resolvers-5.2.1.tgz",
6304
+ "integrity": "sha512-u0+6X58gkjMcxur1wRWokA7XsiiBJ6aK17aPZxhkoYiK5J+HcTx0Vhu9ovXe6H+dVpO6cjrn2FkJTryXEMlryQ==",
6305
+ "requires": {
6306
+ "@standard-schema/utils": "^0.3.0"
6307
+ }
6308
+ },
6309
  "@humanfs/core": {
6310
  "version": "0.19.1",
6311
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@humanfs/core/-/core-0.19.1.tgz",
 
6656
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@opentelemetry/api/-/api-1.9.0.tgz",
6657
  "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="
6658
  },
6659
+ "@radix-ui/number": {
6660
+ "version": "1.1.1",
6661
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/number/-/number-1.1.1.tgz",
6662
+ "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="
6663
+ },
6664
+ "@radix-ui/primitive": {
6665
+ "version": "1.1.3",
6666
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/primitive/-/primitive-1.1.3.tgz",
6667
+ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="
6668
+ },
6669
+ "@radix-ui/react-arrow": {
6670
+ "version": "1.1.7",
6671
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
6672
+ "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
6673
+ "requires": {
6674
+ "@radix-ui/react-primitive": "2.1.3"
6675
+ }
6676
+ },
6677
+ "@radix-ui/react-checkbox": {
6678
+ "version": "1.3.3",
6679
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz",
6680
+ "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==",
6681
+ "requires": {
6682
+ "@radix-ui/primitive": "1.1.3",
6683
+ "@radix-ui/react-compose-refs": "1.1.2",
6684
+ "@radix-ui/react-context": "1.1.2",
6685
+ "@radix-ui/react-presence": "1.1.5",
6686
+ "@radix-ui/react-primitive": "2.1.3",
6687
+ "@radix-ui/react-use-controllable-state": "1.2.2",
6688
+ "@radix-ui/react-use-previous": "1.1.1",
6689
+ "@radix-ui/react-use-size": "1.1.1"
6690
+ }
6691
+ },
6692
+ "@radix-ui/react-collection": {
6693
+ "version": "1.1.7",
6694
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-collection/-/react-collection-1.1.7.tgz",
6695
+ "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==",
6696
+ "requires": {
6697
+ "@radix-ui/react-compose-refs": "1.1.2",
6698
+ "@radix-ui/react-context": "1.1.2",
6699
+ "@radix-ui/react-primitive": "2.1.3",
6700
+ "@radix-ui/react-slot": "1.2.3"
6701
+ }
6702
+ },
6703
+ "@radix-ui/react-compose-refs": {
6704
+ "version": "1.1.2",
6705
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
6706
+ "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
6707
+ "requires": {}
6708
+ },
6709
+ "@radix-ui/react-context": {
6710
+ "version": "1.1.2",
6711
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-context/-/react-context-1.1.2.tgz",
6712
+ "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
6713
+ "requires": {}
6714
+ },
6715
+ "@radix-ui/react-dialog": {
6716
+ "version": "1.1.15",
6717
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz",
6718
+ "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==",
6719
+ "requires": {
6720
+ "@radix-ui/primitive": "1.1.3",
6721
+ "@radix-ui/react-compose-refs": "1.1.2",
6722
+ "@radix-ui/react-context": "1.1.2",
6723
+ "@radix-ui/react-dismissable-layer": "1.1.11",
6724
+ "@radix-ui/react-focus-guards": "1.1.3",
6725
+ "@radix-ui/react-focus-scope": "1.1.7",
6726
+ "@radix-ui/react-id": "1.1.1",
6727
+ "@radix-ui/react-portal": "1.1.9",
6728
+ "@radix-ui/react-presence": "1.1.5",
6729
+ "@radix-ui/react-primitive": "2.1.3",
6730
+ "@radix-ui/react-slot": "1.2.3",
6731
+ "@radix-ui/react-use-controllable-state": "1.2.2",
6732
+ "aria-hidden": "^1.2.4",
6733
+ "react-remove-scroll": "^2.6.3"
6734
+ }
6735
+ },
6736
+ "@radix-ui/react-direction": {
6737
+ "version": "1.1.1",
6738
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-direction/-/react-direction-1.1.1.tgz",
6739
+ "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==",
6740
+ "requires": {}
6741
+ },
6742
+ "@radix-ui/react-dismissable-layer": {
6743
+ "version": "1.1.11",
6744
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
6745
+ "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
6746
+ "requires": {
6747
+ "@radix-ui/primitive": "1.1.3",
6748
+ "@radix-ui/react-compose-refs": "1.1.2",
6749
+ "@radix-ui/react-primitive": "2.1.3",
6750
+ "@radix-ui/react-use-callback-ref": "1.1.1",
6751
+ "@radix-ui/react-use-escape-keydown": "1.1.1"
6752
+ }
6753
+ },
6754
+ "@radix-ui/react-focus-guards": {
6755
+ "version": "1.1.3",
6756
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
6757
+ "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
6758
+ "requires": {}
6759
+ },
6760
+ "@radix-ui/react-focus-scope": {
6761
+ "version": "1.1.7",
6762
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
6763
+ "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
6764
+ "requires": {
6765
+ "@radix-ui/react-compose-refs": "1.1.2",
6766
+ "@radix-ui/react-primitive": "2.1.3",
6767
+ "@radix-ui/react-use-callback-ref": "1.1.1"
6768
+ }
6769
+ },
6770
+ "@radix-ui/react-id": {
6771
+ "version": "1.1.1",
6772
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-id/-/react-id-1.1.1.tgz",
6773
+ "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
6774
+ "requires": {
6775
+ "@radix-ui/react-use-layout-effect": "1.1.1"
6776
+ }
6777
+ },
6778
+ "@radix-ui/react-label": {
6779
+ "version": "2.1.7",
6780
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-label/-/react-label-2.1.7.tgz",
6781
+ "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==",
6782
+ "requires": {
6783
+ "@radix-ui/react-primitive": "2.1.3"
6784
+ }
6785
+ },
6786
+ "@radix-ui/react-popper": {
6787
+ "version": "1.2.8",
6788
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
6789
+ "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
6790
+ "requires": {
6791
+ "@floating-ui/react-dom": "^2.0.0",
6792
+ "@radix-ui/react-arrow": "1.1.7",
6793
+ "@radix-ui/react-compose-refs": "1.1.2",
6794
+ "@radix-ui/react-context": "1.1.2",
6795
+ "@radix-ui/react-primitive": "2.1.3",
6796
+ "@radix-ui/react-use-callback-ref": "1.1.1",
6797
+ "@radix-ui/react-use-layout-effect": "1.1.1",
6798
+ "@radix-ui/react-use-rect": "1.1.1",
6799
+ "@radix-ui/react-use-size": "1.1.1",
6800
+ "@radix-ui/rect": "1.1.1"
6801
+ }
6802
+ },
6803
+ "@radix-ui/react-portal": {
6804
+ "version": "1.1.9",
6805
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
6806
+ "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
6807
+ "requires": {
6808
+ "@radix-ui/react-primitive": "2.1.3",
6809
+ "@radix-ui/react-use-layout-effect": "1.1.1"
6810
+ }
6811
+ },
6812
+ "@radix-ui/react-presence": {
6813
+ "version": "1.1.5",
6814
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
6815
+ "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
6816
+ "requires": {
6817
+ "@radix-ui/react-compose-refs": "1.1.2",
6818
+ "@radix-ui/react-use-layout-effect": "1.1.1"
6819
+ }
6820
+ },
6821
+ "@radix-ui/react-primitive": {
6822
+ "version": "2.1.3",
6823
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
6824
+ "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
6825
+ "requires": {
6826
+ "@radix-ui/react-slot": "1.2.3"
6827
+ }
6828
+ },
6829
+ "@radix-ui/react-scroll-area": {
6830
+ "version": "1.2.10",
6831
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz",
6832
+ "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==",
6833
+ "requires": {
6834
+ "@radix-ui/number": "1.1.1",
6835
+ "@radix-ui/primitive": "1.1.3",
6836
+ "@radix-ui/react-compose-refs": "1.1.2",
6837
+ "@radix-ui/react-context": "1.1.2",
6838
+ "@radix-ui/react-direction": "1.1.1",
6839
+ "@radix-ui/react-presence": "1.1.5",
6840
+ "@radix-ui/react-primitive": "2.1.3",
6841
+ "@radix-ui/react-use-callback-ref": "1.1.1",
6842
+ "@radix-ui/react-use-layout-effect": "1.1.1"
6843
+ }
6844
+ },
6845
+ "@radix-ui/react-select": {
6846
+ "version": "2.2.6",
6847
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-select/-/react-select-2.2.6.tgz",
6848
+ "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==",
6849
+ "requires": {
6850
+ "@radix-ui/number": "1.1.1",
6851
+ "@radix-ui/primitive": "1.1.3",
6852
+ "@radix-ui/react-collection": "1.1.7",
6853
+ "@radix-ui/react-compose-refs": "1.1.2",
6854
+ "@radix-ui/react-context": "1.1.2",
6855
+ "@radix-ui/react-direction": "1.1.1",
6856
+ "@radix-ui/react-dismissable-layer": "1.1.11",
6857
+ "@radix-ui/react-focus-guards": "1.1.3",
6858
+ "@radix-ui/react-focus-scope": "1.1.7",
6859
+ "@radix-ui/react-id": "1.1.1",
6860
+ "@radix-ui/react-popper": "1.2.8",
6861
+ "@radix-ui/react-portal": "1.1.9",
6862
+ "@radix-ui/react-primitive": "2.1.3",
6863
+ "@radix-ui/react-slot": "1.2.3",
6864
+ "@radix-ui/react-use-callback-ref": "1.1.1",
6865
+ "@radix-ui/react-use-controllable-state": "1.2.2",
6866
+ "@radix-ui/react-use-layout-effect": "1.1.1",
6867
+ "@radix-ui/react-use-previous": "1.1.1",
6868
+ "@radix-ui/react-visually-hidden": "1.2.3",
6869
+ "aria-hidden": "^1.2.4",
6870
+ "react-remove-scroll": "^2.6.3"
6871
+ }
6872
+ },
6873
+ "@radix-ui/react-slider": {
6874
+ "version": "1.3.6",
6875
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-slider/-/react-slider-1.3.6.tgz",
6876
+ "integrity": "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==",
6877
+ "requires": {
6878
+ "@radix-ui/number": "1.1.1",
6879
+ "@radix-ui/primitive": "1.1.3",
6880
+ "@radix-ui/react-collection": "1.1.7",
6881
+ "@radix-ui/react-compose-refs": "1.1.2",
6882
+ "@radix-ui/react-context": "1.1.2",
6883
+ "@radix-ui/react-direction": "1.1.1",
6884
+ "@radix-ui/react-primitive": "2.1.3",
6885
+ "@radix-ui/react-use-controllable-state": "1.2.2",
6886
+ "@radix-ui/react-use-layout-effect": "1.1.1",
6887
+ "@radix-ui/react-use-previous": "1.1.1",
6888
+ "@radix-ui/react-use-size": "1.1.1"
6889
+ }
6890
+ },
6891
+ "@radix-ui/react-slot": {
6892
+ "version": "1.2.3",
6893
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
6894
+ "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
6895
+ "requires": {
6896
+ "@radix-ui/react-compose-refs": "1.1.2"
6897
+ }
6898
+ },
6899
+ "@radix-ui/react-use-callback-ref": {
6900
+ "version": "1.1.1",
6901
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
6902
+ "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
6903
+ "requires": {}
6904
+ },
6905
+ "@radix-ui/react-use-controllable-state": {
6906
+ "version": "1.2.2",
6907
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
6908
+ "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
6909
+ "requires": {
6910
+ "@radix-ui/react-use-effect-event": "0.0.2",
6911
+ "@radix-ui/react-use-layout-effect": "1.1.1"
6912
+ }
6913
+ },
6914
+ "@radix-ui/react-use-effect-event": {
6915
+ "version": "0.0.2",
6916
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
6917
+ "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
6918
+ "requires": {
6919
+ "@radix-ui/react-use-layout-effect": "1.1.1"
6920
+ }
6921
+ },
6922
+ "@radix-ui/react-use-escape-keydown": {
6923
+ "version": "1.1.1",
6924
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
6925
+ "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
6926
+ "requires": {
6927
+ "@radix-ui/react-use-callback-ref": "1.1.1"
6928
+ }
6929
+ },
6930
+ "@radix-ui/react-use-layout-effect": {
6931
+ "version": "1.1.1",
6932
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
6933
+ "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
6934
+ "requires": {}
6935
+ },
6936
+ "@radix-ui/react-use-previous": {
6937
+ "version": "1.1.1",
6938
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz",
6939
+ "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==",
6940
+ "requires": {}
6941
+ },
6942
+ "@radix-ui/react-use-rect": {
6943
+ "version": "1.1.1",
6944
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
6945
+ "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
6946
+ "requires": {
6947
+ "@radix-ui/rect": "1.1.1"
6948
+ }
6949
+ },
6950
+ "@radix-ui/react-use-size": {
6951
+ "version": "1.1.1",
6952
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
6953
+ "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
6954
+ "requires": {
6955
+ "@radix-ui/react-use-layout-effect": "1.1.1"
6956
+ }
6957
+ },
6958
+ "@radix-ui/react-visually-hidden": {
6959
+ "version": "1.2.3",
6960
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
6961
+ "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
6962
+ "requires": {
6963
+ "@radix-ui/react-primitive": "2.1.3"
6964
+ }
6965
+ },
6966
+ "@radix-ui/rect": {
6967
+ "version": "1.1.1",
6968
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@radix-ui/rect/-/rect-1.1.1.tgz",
6969
+ "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="
6970
+ },
6971
  "@rtsao/scc": {
6972
  "version": "1.1.0",
6973
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@rtsao/scc/-/scc-1.1.0.tgz",
 
6985
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@standard-schema/spec/-/spec-1.0.0.tgz",
6986
  "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="
6987
  },
6988
+ "@standard-schema/utils": {
6989
+ "version": "0.3.0",
6990
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@standard-schema/utils/-/utils-0.3.0.tgz",
6991
+ "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="
6992
+ },
6993
  "@swc/helpers": {
6994
  "version": "0.5.15",
6995
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@swc/helpers/-/helpers-0.5.15.tgz",
 
7237
  "version": "19.1.9",
7238
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react/-/react-19.1.9.tgz",
7239
  "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==",
7240
+ "devOptional": true,
7241
  "requires": {
7242
  "csstype": "^3.0.2"
7243
  }
 
7246
  "version": "19.1.7",
7247
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/react-dom/-/react-dom-19.1.7.tgz",
7248
  "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
7249
+ "devOptional": true,
7250
  "requires": {}
7251
  },
7252
  "@typescript-eslint/eslint-plugin": {
 
7625
  "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
7626
  "dev": true
7627
  },
7628
+ "aria-hidden": {
7629
+ "version": "1.2.6",
7630
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/aria-hidden/-/aria-hidden-1.2.6.tgz",
7631
+ "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
7632
+ "requires": {
7633
+ "tslib": "^2.0.0"
7634
+ }
7635
+ },
7636
  "aria-query": {
7637
  "version": "5.3.2",
7638
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/aria-query/-/aria-query-5.3.2.tgz",
 
7863
  "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
7864
  "dev": true
7865
  },
7866
+ "class-variance-authority": {
7867
+ "version": "0.7.1",
7868
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
7869
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
7870
+ "requires": {
7871
+ "clsx": "^2.1.1"
7872
+ }
7873
+ },
7874
  "client-only": {
7875
  "version": "0.0.1",
7876
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/client-only/-/client-only-0.0.1.tgz",
7877
  "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
7878
  },
7879
+ "clsx": {
7880
+ "version": "2.1.1",
7881
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/clsx/-/clsx-2.1.1.tgz",
7882
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="
7883
+ },
7884
  "color": {
7885
  "version": "4.2.3",
7886
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/color/-/color-4.2.3.tgz",
 
7922
  "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
7923
  "dev": true
7924
  },
7925
+ "core-util-is": {
7926
+ "version": "1.0.3",
7927
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/core-util-is/-/core-util-is-1.0.3.tgz",
7928
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
7929
+ },
7930
  "cross-spawn": {
7931
  "version": "7.0.6",
7932
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/cross-spawn/-/cross-spawn-7.0.6.tgz",
 
7942
  "version": "3.1.3",
7943
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/csstype/-/csstype-3.1.3.tgz",
7944
  "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
7945
+ "devOptional": true
7946
  },
7947
  "damerau-levenshtein": {
7948
  "version": "1.0.8",
 
8031
  "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
8032
  "devOptional": true
8033
  },
8034
+ "detect-node-es": {
8035
+ "version": "1.1.0",
8036
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/detect-node-es/-/detect-node-es-1.1.0.tgz",
8037
+ "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
8038
+ },
8039
  "doctrine": {
8040
  "version": "2.1.0",
8041
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/doctrine/-/doctrine-2.1.0.tgz",
 
8045
  "esutils": "^2.0.2"
8046
  }
8047
  },
8048
+ "docx": {
8049
+ "version": "9.5.1",
8050
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/docx/-/docx-9.5.1.tgz",
8051
+ "integrity": "sha512-ABDI7JEirFD2+bHhOBlsGZxaG1UgZb2M/QMKhLSDGgVNhxDesTCDcP+qoDnDGjZ4EOXTRfUjUgwHVuZ6VSTfWQ==",
8052
+ "requires": {
8053
+ "@types/node": "^24.0.1",
8054
+ "hash.js": "^1.1.7",
8055
+ "jszip": "^3.10.1",
8056
+ "nanoid": "^5.1.3",
8057
+ "xml": "^1.0.1",
8058
+ "xml-js": "^1.6.8"
8059
+ },
8060
+ "dependencies": {
8061
+ "@types/node": {
8062
+ "version": "24.3.0",
8063
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/@types/node/-/node-24.3.0.tgz",
8064
+ "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==",
8065
+ "requires": {
8066
+ "undici-types": "~7.10.0"
8067
+ }
8068
+ },
8069
+ "nanoid": {
8070
+ "version": "5.1.5",
8071
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/nanoid/-/nanoid-5.1.5.tgz",
8072
+ "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw=="
8073
+ },
8074
+ "undici-types": {
8075
+ "version": "7.10.0",
8076
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/undici-types/-/undici-types-7.10.0.tgz",
8077
+ "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="
8078
+ }
8079
+ }
8080
+ },
8081
  "dunder-proto": {
8082
  "version": "1.0.1",
8083
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/dunder-proto/-/dunder-proto-1.0.1.tgz",
 
8697
  "math-intrinsics": "^1.1.0"
8698
  }
8699
  },
8700
+ "get-nonce": {
8701
+ "version": "1.0.1",
8702
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/get-nonce/-/get-nonce-1.0.1.tgz",
8703
+ "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="
8704
+ },
8705
  "get-proto": {
8706
  "version": "1.0.1",
8707
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/get-proto/-/get-proto-1.0.1.tgz",
 
8820
  "has-symbols": "^1.0.3"
8821
  }
8822
  },
8823
+ "hash.js": {
8824
+ "version": "1.1.7",
8825
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/hash.js/-/hash.js-1.1.7.tgz",
8826
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
8827
+ "requires": {
8828
+ "inherits": "^2.0.3",
8829
+ "minimalistic-assert": "^1.0.1"
8830
+ }
8831
+ },
8832
  "hasown": {
8833
  "version": "2.0.2",
8834
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/hasown/-/hasown-2.0.2.tgz",
 
8844
  "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
8845
  "dev": true
8846
  },
8847
+ "immediate": {
8848
+ "version": "3.0.6",
8849
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/immediate/-/immediate-3.0.6.tgz",
8850
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
8851
+ },
8852
  "import-fresh": {
8853
  "version": "3.3.1",
8854
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/import-fresh/-/import-fresh-3.3.1.tgz",
 
8865
  "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
8866
  "dev": true
8867
  },
8868
+ "inherits": {
8869
+ "version": "2.0.4",
8870
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/inherits/-/inherits-2.0.4.tgz",
8871
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
8872
+ },
8873
  "internal-slot": {
8874
  "version": "1.1.0",
8875
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/internal-slot/-/internal-slot-1.1.0.tgz",
 
9212
  "object.values": "^1.1.6"
9213
  }
9214
  },
9215
+ "jszip": {
9216
+ "version": "3.10.1",
9217
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/jszip/-/jszip-3.10.1.tgz",
9218
+ "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
9219
+ "requires": {
9220
+ "lie": "~3.3.0",
9221
+ "pako": "~1.0.2",
9222
+ "readable-stream": "~2.3.6",
9223
+ "setimmediate": "^1.0.5"
9224
+ }
9225
+ },
9226
  "keyv": {
9227
  "version": "4.5.4",
9228
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/keyv/-/keyv-4.5.4.tgz",
 
9257
  "type-check": "~0.4.0"
9258
  }
9259
  },
9260
+ "lie": {
9261
+ "version": "3.3.0",
9262
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lie/-/lie-3.3.0.tgz",
9263
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
9264
+ "requires": {
9265
+ "immediate": "~3.0.5"
9266
+ }
9267
+ },
9268
  "lightningcss": {
9269
  "version": "1.30.1",
9270
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lightningcss/-/lightningcss-1.30.1.tgz",
 
9378
  "js-tokens": "^3.0.0 || ^4.0.0"
9379
  }
9380
  },
9381
+ "lucide-react": {
9382
+ "version": "0.539.0",
9383
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/lucide-react/-/lucide-react-0.539.0.tgz",
9384
+ "integrity": "sha512-VVISr+VF2krO91FeuCrm1rSOLACQUYVy7NQkzrOty52Y8TlTPcXcMdQFj9bYzBgXbWCiywlwSZ3Z8u6a+6bMlg==",
9385
+ "requires": {}
9386
+ },
9387
  "magic-string": {
9388
  "version": "0.30.17",
9389
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/magic-string/-/magic-string-0.30.17.tgz",
 
9415
  "picomatch": "^2.3.1"
9416
  }
9417
  },
9418
+ "minimalistic-assert": {
9419
+ "version": "1.0.1",
9420
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
9421
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A=="
9422
+ },
9423
  "minimatch": {
9424
  "version": "3.1.2",
9425
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/minimatch/-/minimatch-3.1.2.tgz",
 
9642
  "p-limit": "^3.0.2"
9643
  }
9644
  },
9645
+ "pako": {
9646
+ "version": "1.0.11",
9647
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/pako/-/pako-1.0.11.tgz",
9648
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
9649
+ },
9650
  "parent-module": {
9651
  "version": "1.0.1",
9652
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/parent-module/-/parent-module-1.0.1.tgz",
 
9708
  "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
9709
  "dev": true
9710
  },
9711
+ "process-nextick-args": {
9712
+ "version": "2.0.1",
9713
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
9714
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
9715
+ },
9716
  "prop-types": {
9717
  "version": "15.8.1",
9718
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/prop-types/-/prop-types-15.8.1.tgz",
 
9749
  "scheduler": "^0.26.0"
9750
  }
9751
  },
9752
+ "react-hook-form": {
9753
+ "version": "7.62.0",
9754
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-hook-form/-/react-hook-form-7.62.0.tgz",
9755
+ "integrity": "sha512-7KWFejc98xqG/F4bAxpL41NB3o1nnvQO1RWZT3TqRZYL8RryQETGfEdVnJN2fy1crCiBLLjkRBVK05j24FxJGA==",
9756
+ "requires": {}
9757
+ },
9758
  "react-is": {
9759
  "version": "16.13.1",
9760
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-is/-/react-is-16.13.1.tgz",
9761
  "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
9762
  "dev": true
9763
  },
9764
+ "react-remove-scroll": {
9765
+ "version": "2.7.1",
9766
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
9767
+ "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
9768
+ "requires": {
9769
+ "react-remove-scroll-bar": "^2.3.7",
9770
+ "react-style-singleton": "^2.2.3",
9771
+ "tslib": "^2.1.0",
9772
+ "use-callback-ref": "^1.3.3",
9773
+ "use-sidecar": "^1.1.3"
9774
+ }
9775
+ },
9776
+ "react-remove-scroll-bar": {
9777
+ "version": "2.3.8",
9778
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
9779
+ "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
9780
+ "requires": {
9781
+ "react-style-singleton": "^2.2.2",
9782
+ "tslib": "^2.0.0"
9783
+ }
9784
+ },
9785
+ "react-style-singleton": {
9786
+ "version": "2.2.3",
9787
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
9788
+ "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
9789
+ "requires": {
9790
+ "get-nonce": "^1.0.0",
9791
+ "tslib": "^2.0.0"
9792
+ }
9793
+ },
9794
+ "readable-stream": {
9795
+ "version": "2.3.8",
9796
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/readable-stream/-/readable-stream-2.3.8.tgz",
9797
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
9798
+ "requires": {
9799
+ "core-util-is": "~1.0.0",
9800
+ "inherits": "~2.0.3",
9801
+ "isarray": "~1.0.0",
9802
+ "process-nextick-args": "~2.0.0",
9803
+ "safe-buffer": "~5.1.1",
9804
+ "string_decoder": "~1.1.1",
9805
+ "util-deprecate": "~1.0.1"
9806
+ },
9807
+ "dependencies": {
9808
+ "isarray": {
9809
+ "version": "1.0.0",
9810
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/isarray/-/isarray-1.0.0.tgz",
9811
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
9812
+ }
9813
+ }
9814
+ },
9815
  "reflect.getprototypeof": {
9816
  "version": "1.0.10",
9817
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
 
9893
  "isarray": "^2.0.5"
9894
  }
9895
  },
9896
+ "safe-buffer": {
9897
+ "version": "5.1.2",
9898
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/safe-buffer/-/safe-buffer-5.1.2.tgz",
9899
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
9900
+ },
9901
  "safe-push-apply": {
9902
  "version": "1.0.0",
9903
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
 
9919
  "is-regex": "^1.2.1"
9920
  }
9921
  },
9922
+ "sax": {
9923
+ "version": "1.4.1",
9924
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/sax/-/sax-1.4.1.tgz",
9925
+ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
9926
+ },
9927
  "scheduler": {
9928
  "version": "0.26.0",
9929
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/scheduler/-/scheduler-0.26.0.tgz",
 
9972
  "es-object-atoms": "^1.0.0"
9973
  }
9974
  },
9975
+ "setimmediate": {
9976
+ "version": "1.0.5",
9977
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/setimmediate/-/setimmediate-1.0.5.tgz",
9978
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
9979
+ },
9980
  "sharp": {
9981
  "version": "0.34.3",
9982
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/sharp/-/sharp-0.34.3.tgz",
 
10103
  "internal-slot": "^1.1.0"
10104
  }
10105
  },
10106
+ "string_decoder": {
10107
+ "version": "1.1.1",
10108
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/string_decoder/-/string_decoder-1.1.1.tgz",
10109
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
10110
+ "requires": {
10111
+ "safe-buffer": "~5.1.0"
10112
+ }
10113
+ },
10114
  "string.prototype.includes": {
10115
  "version": "2.0.1",
10116
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
 
10218
  "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
10219
  "dev": true
10220
  },
10221
+ "tailwind-merge": {
10222
+ "version": "3.3.1",
10223
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tailwind-merge/-/tailwind-merge-3.3.1.tgz",
10224
+ "integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="
10225
+ },
10226
  "tailwindcss": {
10227
  "version": "4.1.11",
10228
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tailwindcss/-/tailwindcss-4.1.11.tgz",
 
10312
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tslib/-/tslib-2.8.1.tgz",
10313
  "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
10314
  },
10315
+ "tw-animate-css": {
10316
+ "version": "1.3.7",
10317
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/tw-animate-css/-/tw-animate-css-1.3.7.tgz",
10318
+ "integrity": "sha512-lvLb3hTIpB5oGsk8JmLoAjeCHV58nKa2zHYn8yWOoG5JJusH3bhJlF2DLAZ/5NmJ+jyH3ssiAx/2KmbhavJy/A==",
10319
+ "dev": true
10320
+ },
10321
  "type-check": {
10322
  "version": "0.4.0",
10323
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/type-check/-/type-check-0.4.0.tgz",
 
10441
  "punycode": "^2.1.0"
10442
  }
10443
  },
10444
+ "use-callback-ref": {
10445
+ "version": "1.3.3",
10446
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
10447
+ "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
10448
+ "requires": {
10449
+ "tslib": "^2.0.0"
10450
+ }
10451
+ },
10452
+ "use-sidecar": {
10453
+ "version": "1.1.3",
10454
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/use-sidecar/-/use-sidecar-1.1.3.tgz",
10455
+ "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
10456
+ "requires": {
10457
+ "detect-node-es": "^1.1.0",
10458
+ "tslib": "^2.0.0"
10459
+ }
10460
+ },
10461
+ "util-deprecate": {
10462
+ "version": "1.0.2",
10463
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/util-deprecate/-/util-deprecate-1.0.2.tgz",
10464
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
10465
+ },
10466
  "which": {
10467
  "version": "2.0.2",
10468
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/which/-/which-2.0.2.tgz",
 
10539
  "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
10540
  "dev": true
10541
  },
10542
+ "xml": {
10543
+ "version": "1.0.1",
10544
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/xml/-/xml-1.0.1.tgz",
10545
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw=="
10546
+ },
10547
+ "xml-js": {
10548
+ "version": "1.6.11",
10549
+ "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/xml-js/-/xml-js-1.6.11.tgz",
10550
+ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
10551
+ "requires": {
10552
+ "sax": "^1.2.4"
10553
+ }
10554
+ },
10555
  "yallist": {
10556
  "version": "5.0.0",
10557
  "resolved": "http://artifactory-build.taboolasyndication.com:80/artifactory/api/npm/npm-public/yallist/-/yallist-5.0.0.tgz",
package.json CHANGED
@@ -11,10 +11,24 @@
11
  "dependencies": {
12
  "@ai-sdk/openai": "^2.0.0",
13
  "@ai-sdk/react": "^2.0.1",
 
 
 
 
 
 
 
 
14
  "ai": "^5.0.1",
 
 
 
 
15
  "next": "15.4.5",
16
  "react": "19.1.0",
17
  "react-dom": "19.1.0",
 
 
18
  "zod": "^3.25.76"
19
  },
20
  "devDependencies": {
@@ -26,6 +40,7 @@
26
  "eslint": "^9",
27
  "eslint-config-next": "15.4.5",
28
  "tailwindcss": "^4",
 
29
  "typescript": "^5"
30
  }
31
  }
 
11
  "dependencies": {
12
  "@ai-sdk/openai": "^2.0.0",
13
  "@ai-sdk/react": "^2.0.1",
14
+ "@hookform/resolvers": "^5.2.1",
15
+ "@radix-ui/react-checkbox": "^1.3.3",
16
+ "@radix-ui/react-dialog": "^1.1.15",
17
+ "@radix-ui/react-label": "^2.1.7",
18
+ "@radix-ui/react-scroll-area": "^1.2.10",
19
+ "@radix-ui/react-select": "^2.2.6",
20
+ "@radix-ui/react-slider": "^1.3.6",
21
+ "@radix-ui/react-slot": "^1.2.3",
22
  "ai": "^5.0.1",
23
+ "class-variance-authority": "^0.7.1",
24
+ "clsx": "^2.1.1",
25
+ "docx": "^9.5.1",
26
+ "lucide-react": "^0.539.0",
27
  "next": "15.4.5",
28
  "react": "19.1.0",
29
  "react-dom": "19.1.0",
30
+ "react-hook-form": "^7.62.0",
31
+ "tailwind-merge": "^3.3.1",
32
  "zod": "^3.25.76"
33
  },
34
  "devDependencies": {
 
40
  "eslint": "^9",
41
  "eslint-config-next": "15.4.5",
42
  "tailwindcss": "^4",
43
+ "tw-animate-css": "^1.3.7",
44
  "typescript": "^5"
45
  }
46
  }
src/app/globals.css CHANGED
@@ -1,26 +1,122 @@
1
  @import "tailwindcss";
 
2
 
3
- :root {
4
- --background: #ffffff;
5
- --foreground: #171717;
6
- }
7
 
8
  @theme inline {
9
  --color-background: var(--background);
10
  --color-foreground: var(--foreground);
11
  --font-sans: var(--font-geist-sans);
12
  --font-mono: var(--font-geist-mono);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  }
14
 
15
- @media (prefers-color-scheme: dark) {
16
- :root {
17
- --background: #0a0a0a;
18
- --foreground: #ededed;
19
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  }
21
 
22
- body {
23
- background: var(--background);
24
- color: var(--foreground);
25
- font-family: Arial, Helvetica, sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
 
1
  @import "tailwindcss";
2
+ @import "tw-animate-css";
3
 
4
+ @custom-variant dark (&:is(.dark *));
 
 
 
5
 
6
  @theme inline {
7
  --color-background: var(--background);
8
  --color-foreground: var(--foreground);
9
  --font-sans: var(--font-geist-sans);
10
  --font-mono: var(--font-geist-mono);
11
+ --color-sidebar-ring: var(--sidebar-ring);
12
+ --color-sidebar-border: var(--sidebar-border);
13
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
14
+ --color-sidebar-accent: var(--sidebar-accent);
15
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
16
+ --color-sidebar-primary: var(--sidebar-primary);
17
+ --color-sidebar-foreground: var(--sidebar-foreground);
18
+ --color-sidebar: var(--sidebar);
19
+ --color-chart-5: var(--chart-5);
20
+ --color-chart-4: var(--chart-4);
21
+ --color-chart-3: var(--chart-3);
22
+ --color-chart-2: var(--chart-2);
23
+ --color-chart-1: var(--chart-1);
24
+ --color-ring: var(--ring);
25
+ --color-input: var(--input);
26
+ --color-border: var(--border);
27
+ --color-destructive: var(--destructive);
28
+ --color-accent-foreground: var(--accent-foreground);
29
+ --color-accent: var(--accent);
30
+ --color-muted-foreground: var(--muted-foreground);
31
+ --color-muted: var(--muted);
32
+ --color-secondary-foreground: var(--secondary-foreground);
33
+ --color-secondary: var(--secondary);
34
+ --color-primary-foreground: var(--primary-foreground);
35
+ --color-primary: var(--primary);
36
+ --color-popover-foreground: var(--popover-foreground);
37
+ --color-popover: var(--popover);
38
+ --color-card-foreground: var(--card-foreground);
39
+ --color-card: var(--card);
40
+ --radius-sm: calc(var(--radius) - 4px);
41
+ --radius-md: calc(var(--radius) - 2px);
42
+ --radius-lg: var(--radius);
43
+ --radius-xl: calc(var(--radius) + 4px);
44
  }
45
 
46
+ :root {
47
+ --radius: 0.625rem;
48
+ --background: oklch(1 0 0);
49
+ --foreground: oklch(0.145 0 0);
50
+ --card: oklch(1 0 0);
51
+ --card-foreground: oklch(0.145 0 0);
52
+ --popover: oklch(1 0 0);
53
+ --popover-foreground: oklch(0.145 0 0);
54
+ --primary: oklch(0.205 0 0);
55
+ --primary-foreground: oklch(0.985 0 0);
56
+ --secondary: oklch(0.97 0 0);
57
+ --secondary-foreground: oklch(0.205 0 0);
58
+ --muted: oklch(0.97 0 0);
59
+ --muted-foreground: oklch(0.556 0 0);
60
+ --accent: oklch(0.97 0 0);
61
+ --accent-foreground: oklch(0.205 0 0);
62
+ --destructive: oklch(0.577 0.245 27.325);
63
+ --border: oklch(0.922 0 0);
64
+ --input: oklch(0.922 0 0);
65
+ --ring: oklch(0.708 0 0);
66
+ --chart-1: oklch(0.646 0.222 41.116);
67
+ --chart-2: oklch(0.6 0.118 184.704);
68
+ --chart-3: oklch(0.398 0.07 227.392);
69
+ --chart-4: oklch(0.828 0.189 84.429);
70
+ --chart-5: oklch(0.769 0.188 70.08);
71
+ --sidebar: oklch(0.985 0 0);
72
+ --sidebar-foreground: oklch(0.145 0 0);
73
+ --sidebar-primary: oklch(0.205 0 0);
74
+ --sidebar-primary-foreground: oklch(0.985 0 0);
75
+ --sidebar-accent: oklch(0.97 0 0);
76
+ --sidebar-accent-foreground: oklch(0.205 0 0);
77
+ --sidebar-border: oklch(0.922 0 0);
78
+ --sidebar-ring: oklch(0.708 0 0);
79
  }
80
 
81
+ .dark {
82
+ --background: oklch(0.145 0 0);
83
+ --foreground: oklch(0.985 0 0);
84
+ --card: oklch(0.205 0 0);
85
+ --card-foreground: oklch(0.985 0 0);
86
+ --popover: oklch(0.205 0 0);
87
+ --popover-foreground: oklch(0.985 0 0);
88
+ --primary: oklch(0.922 0 0);
89
+ --primary-foreground: oklch(0.205 0 0);
90
+ --secondary: oklch(0.269 0 0);
91
+ --secondary-foreground: oklch(0.985 0 0);
92
+ --muted: oklch(0.269 0 0);
93
+ --muted-foreground: oklch(0.708 0 0);
94
+ --accent: oklch(0.269 0 0);
95
+ --accent-foreground: oklch(0.985 0 0);
96
+ --destructive: oklch(0.704 0.191 22.216);
97
+ --border: oklch(1 0 0 / 10%);
98
+ --input: oklch(1 0 0 / 15%);
99
+ --ring: oklch(0.556 0 0);
100
+ --chart-1: oklch(0.488 0.243 264.376);
101
+ --chart-2: oklch(0.696 0.17 162.48);
102
+ --chart-3: oklch(0.769 0.188 70.08);
103
+ --chart-4: oklch(0.627 0.265 303.9);
104
+ --chart-5: oklch(0.645 0.246 16.439);
105
+ --sidebar: oklch(0.205 0 0);
106
+ --sidebar-foreground: oklch(0.985 0 0);
107
+ --sidebar-primary: oklch(0.488 0.243 264.376);
108
+ --sidebar-primary-foreground: oklch(0.985 0 0);
109
+ --sidebar-accent: oklch(0.269 0 0);
110
+ --sidebar-accent-foreground: oklch(0.985 0 0);
111
+ --sidebar-border: oklch(1 0 0 / 10%);
112
+ --sidebar-ring: oklch(0.556 0 0);
113
+ }
114
+
115
+ @layer base {
116
+ * {
117
+ @apply border-border outline-ring/50;
118
+ }
119
+ body {
120
+ @apply bg-background text-foreground;
121
+ }
122
  }
src/app/page.tsx CHANGED
@@ -6,6 +6,9 @@ import { QuestionParameterForm } from '@/components/question-creation';
6
  import { QuestionList } from '@/components/question-output';
7
  import { SourceArticle } from '@/components/source-article';
8
  import { QuestionType, QuestionParameters, GeneratedQuestion } from '@/types/quiz';
 
 
 
9
 
10
  const QUESTION_TYPES: QuestionType[] = [
11
  { id: 'cloze', name: 'Cloze (Fill-in-the-blank)', icon: '🔤', description: 'Fill in missing words or phrases' },
@@ -113,21 +116,18 @@ export default function QuestionBuilder() {
113
  💬 Question Builder
114
  </h2>
115
  )}
116
- <button
117
  onClick={() => setIsQuestionBuilderCollapsed(!isQuestionBuilderCollapsed)}
118
- className="p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-600 rounded-lg transition-colors"
 
119
  title={isQuestionBuilderCollapsed ? 'Expand Question Builder' : 'Collapse Question Builder'}
120
  >
121
  {isQuestionBuilderCollapsed ? (
122
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
123
- <polyline points="9,18 15,12 9,6"></polyline>
124
- </svg>
125
  ) : (
126
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
127
- <polyline points="15,18 9,12 15,6"></polyline>
128
- </svg>
129
  )}
130
- </button>
131
  </div>
132
 
133
  {!isQuestionBuilderCollapsed && (
@@ -142,19 +142,20 @@ export default function QuestionBuilder() {
142
 
143
  <div className="space-y-2">
144
  {QUESTION_TYPES.map((type) => (
145
- <button
146
  key={type.id}
147
  onClick={() => handleQuestionTypeSelect(type)}
148
- className="w-full p-3 text-left border border-gray-200 dark:border-gray-500 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
 
149
  >
150
  <div className="flex items-center space-x-3">
151
  <span className="text-lg">{type.icon}</span>
152
- <div>
153
- <div className="font-medium text-gray-900 dark:text-gray-100">{type.name}</div>
154
- <div className="text-sm text-gray-500 dark:text-gray-400">{type.description}</div>
155
  </div>
156
  </div>
157
- </button>
158
  ))}
159
  </div>
160
  </div>
@@ -164,7 +165,7 @@ export default function QuestionBuilder() {
164
  <div className="space-y-4">
165
  <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700 rounded-lg p-4">
166
  <p className="text-blue-800 dark:text-blue-200">
167
- Great choice! Let's configure your {selectedQuestionType.name} question.
168
  </p>
169
  </div>
170
 
@@ -175,19 +176,19 @@ export default function QuestionBuilder() {
175
  />
176
 
177
  <div className="flex space-x-2">
178
- <button
179
  onClick={() => setCurrentStep('type-selection')}
180
- className="px-4 py-2 text-gray-600 dark:text-gray-300 border border-gray-300 dark:border-gray-500 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700"
181
  >
182
  Back
183
- </button>
184
- <button
185
  onClick={generateQuestion}
186
  disabled={isGenerating}
187
- className="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-500"
188
  >
189
  {isGenerating ? 'Generating...' : 'Generate Question'}
190
- </button>
191
  </div>
192
  </div>
193
  )}
@@ -216,19 +217,18 @@ export default function QuestionBuilder() {
216
  {!isQuestionBuilderCollapsed && (
217
  <div className="p-4 border-t border-gray-200 dark:border-gray-600">
218
  <form onSubmit={handleSubmit} className="flex space-x-2">
219
- <input
220
  value={input}
221
  onChange={handleInputChange}
222
  placeholder="Ask for modifications or help..."
223
- className="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-500 rounded-lg focus:ring-2 focus:ring-blue-500 dark:bg-gray-800 dark:text-gray-100"
224
  />
225
- <button
226
  type="submit"
227
  disabled={isLoading}
228
- className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-gray-500"
229
  >
230
  Send
231
- </button>
232
  </form>
233
  </div>
234
  )}
 
6
  import { QuestionList } from '@/components/question-output';
7
  import { SourceArticle } from '@/components/source-article';
8
  import { QuestionType, QuestionParameters, GeneratedQuestion } from '@/types/quiz';
9
+ import { Button } from '@/components/ui/button';
10
+ import { Input } from '@/components/ui/input';
11
+ import { ChevronRight, ChevronLeft } from 'lucide-react';
12
 
13
  const QUESTION_TYPES: QuestionType[] = [
14
  { id: 'cloze', name: 'Cloze (Fill-in-the-blank)', icon: '🔤', description: 'Fill in missing words or phrases' },
 
116
  💬 Question Builder
117
  </h2>
118
  )}
119
+ <Button
120
  onClick={() => setIsQuestionBuilderCollapsed(!isQuestionBuilderCollapsed)}
121
+ variant="ghost"
122
+ size="icon"
123
  title={isQuestionBuilderCollapsed ? 'Expand Question Builder' : 'Collapse Question Builder'}
124
  >
125
  {isQuestionBuilderCollapsed ? (
126
+ <ChevronRight className="h-4 w-4" />
 
 
127
  ) : (
128
+ <ChevronLeft className="h-4 w-4" />
 
 
129
  )}
130
+ </Button>
131
  </div>
132
 
133
  {!isQuestionBuilderCollapsed && (
 
142
 
143
  <div className="space-y-2">
144
  {QUESTION_TYPES.map((type) => (
145
+ <Button
146
  key={type.id}
147
  onClick={() => handleQuestionTypeSelect(type)}
148
+ variant="outline"
149
+ className="w-full justify-start p-3 h-auto"
150
  >
151
  <div className="flex items-center space-x-3">
152
  <span className="text-lg">{type.icon}</span>
153
+ <div className="text-left">
154
+ <div className="font-medium">{type.name}</div>
155
+ <div className="text-sm text-muted-foreground">{type.description}</div>
156
  </div>
157
  </div>
158
+ </Button>
159
  ))}
160
  </div>
161
  </div>
 
165
  <div className="space-y-4">
166
  <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-700 rounded-lg p-4">
167
  <p className="text-blue-800 dark:text-blue-200">
168
+ Great choice! Let&apos;s configure your {selectedQuestionType.name} question.
169
  </p>
170
  </div>
171
 
 
176
  />
177
 
178
  <div className="flex space-x-2">
179
+ <Button
180
  onClick={() => setCurrentStep('type-selection')}
181
+ variant="outline"
182
  >
183
  Back
184
+ </Button>
185
+ <Button
186
  onClick={generateQuestion}
187
  disabled={isGenerating}
188
+ className="flex-1"
189
  >
190
  {isGenerating ? 'Generating...' : 'Generate Question'}
191
+ </Button>
192
  </div>
193
  </div>
194
  )}
 
217
  {!isQuestionBuilderCollapsed && (
218
  <div className="p-4 border-t border-gray-200 dark:border-gray-600">
219
  <form onSubmit={handleSubmit} className="flex space-x-2">
220
+ <Input
221
  value={input}
222
  onChange={handleInputChange}
223
  placeholder="Ask for modifications or help..."
224
+ className="flex-1"
225
  />
226
+ <Button
227
  type="submit"
228
  disabled={isLoading}
 
229
  >
230
  Send
231
+ </Button>
232
  </form>
233
  </div>
234
  )}
src/components/question-creation/inputs/CheckboxInput.tsx CHANGED
@@ -1,5 +1,8 @@
1
  'use client';
2
 
 
 
 
3
  export interface CheckboxInputProps {
4
  label: string;
5
  value?: boolean;
@@ -24,30 +27,27 @@ export default function CheckboxInput({
24
  id,
25
  }: CheckboxInputProps) {
26
  const currentValue = value ?? defaultValue;
27
- const inputId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
28
 
29
  return (
30
- <div className={`flex items-start ${className}`}>
31
- <div className="flex items-center h-5">
32
- <input
33
- type="checkbox"
34
- id={inputId}
35
- checked={currentValue}
36
- onChange={(e) => onChange(e.target.checked)}
37
- disabled={disabled}
38
- required={required}
39
- className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 disabled:opacity-50 disabled:cursor-not-allowed"
40
- />
41
- </div>
42
- <div className="ml-3">
43
- <label htmlFor={inputId} className="text-sm font-medium text-gray-700 dark:text-gray-300">
44
  {label}
45
- {required && <span className="text-red-500 ml-1">*</span>}
46
- </label>
47
  {helpText && (
48
- <div className="text-xs text-gray-500 dark:text-gray-400 mt-1">
49
  {helpText}
50
- </div>
51
  )}
52
  </div>
53
  </div>
 
1
  'use client';
2
 
3
+ import { Checkbox } from '@/components/ui/checkbox';
4
+ import { Label } from '@/components/ui/label';
5
+
6
  export interface CheckboxInputProps {
7
  label: string;
8
  value?: boolean;
 
27
  id,
28
  }: CheckboxInputProps) {
29
  const currentValue = value ?? defaultValue;
30
+ const inputId = id || `checkbox-${Math.random().toString(36).substring(2, 11)}`;
31
 
32
  return (
33
+ <div className={`flex items-start space-x-3 ${className}`}>
34
+ <Checkbox
35
+ id={inputId}
36
+ checked={currentValue}
37
+ onCheckedChange={onChange}
38
+ disabled={disabled}
39
+ required={required}
40
+ className="mt-0.5"
41
+ />
42
+ <div className="grid gap-1.5 leading-none">
43
+ <Label htmlFor={inputId} className="text-sm font-medium">
 
 
 
44
  {label}
45
+ {required && <span className="text-destructive ml-1">*</span>}
46
+ </Label>
47
  {helpText && (
48
+ <p className="text-xs text-muted-foreground">
49
  {helpText}
50
+ </p>
51
  )}
52
  </div>
53
  </div>
src/components/question-creation/inputs/RangeInput.tsx CHANGED
@@ -1,5 +1,8 @@
1
  'use client';
2
 
 
 
 
3
  export interface RangeInputProps {
4
  label: string;
5
  value?: number;
@@ -33,26 +36,25 @@ export default function RangeInput({
33
 
34
  return (
35
  <div className={className}>
36
- <label className="block text-sm font-medium mb-2 text-gray-700 dark:text-gray-300">
37
  {label}
38
- </label>
39
- <input
40
- type="range"
41
- min={min}
42
- max={max}
43
  step={step}
44
- value={currentValue}
45
- onChange={(e) => onChange(parseInt(e.target.value))}
46
  disabled={disabled}
47
- className="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
48
  />
49
  {showValue && (
50
- <div className="text-center text-sm text-gray-600 dark:text-gray-400 mt-1">
51
  {currentValue} {valueUnit} {helpText}
52
  </div>
53
  )}
54
  {!showValue && helpText && (
55
- <div className="text-xs text-gray-500 dark:text-gray-400 mt-1">
56
  {helpText}
57
  </div>
58
  )}
 
1
  'use client';
2
 
3
+ import { Slider } from '@/components/ui/slider';
4
+ import { Label } from '@/components/ui/label';
5
+
6
  export interface RangeInputProps {
7
  label: string;
8
  value?: number;
 
36
 
37
  return (
38
  <div className={className}>
39
+ <Label>
40
  {label}
41
+ </Label>
42
+ <Slider
43
+ min={min}
44
+ max={max}
 
45
  step={step}
46
+ value={[currentValue]}
47
+ onValueChange={([val]) => onChange(val)}
48
  disabled={disabled}
49
+ className="mt-2"
50
  />
51
  {showValue && (
52
+ <div className="text-center text-sm text-muted-foreground mt-1">
53
  {currentValue} {valueUnit} {helpText}
54
  </div>
55
  )}
56
  {!showValue && helpText && (
57
+ <div className="text-xs text-muted-foreground mt-1">
58
  {helpText}
59
  </div>
60
  )}
src/components/question-creation/inputs/SelectInput.tsx CHANGED
@@ -1,5 +1,14 @@
1
  'use client';
2
 
 
 
 
 
 
 
 
 
 
3
  export interface SelectOption {
4
  value: string | number;
5
  label: string;
@@ -25,43 +34,41 @@ export default function SelectInput({
25
  onChange,
26
  className = '',
27
  disabled = false,
28
- placeholder,
29
  helpText,
30
  }: SelectInputProps) {
31
  const currentValue = value ?? defaultValue;
32
- const baseClasses = "w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed";
33
 
34
  return (
35
  <div className={className}>
36
- <label className="block text-sm font-medium mb-2 text-gray-700 dark:text-gray-300">
37
  {label}
38
- </label>
39
- <select
40
- value={currentValue?.toString() || ''}
41
- onChange={(e) => {
42
- const selectedOption = options.find(opt => opt.value.toString() === e.target.value);
43
  if (selectedOption) {
44
  onChange(selectedOption.value);
45
  }
46
  }}
47
  disabled={disabled}
48
- className={`${baseClasses} bg-white dark:bg-gray-700 text-gray-900 dark:text-white border-gray-300 dark:border-gray-600`}
49
  >
50
- {placeholder && (
51
- <option value="" disabled>
52
- {placeholder}
53
- </option>
54
- )}
55
- {options.map((option) => (
56
- <option key={option.value.toString()} value={option.value.toString()}>
57
- {option.label}
58
- </option>
59
- ))}
60
- </select>
61
  {helpText && (
62
- <div className="text-xs text-gray-500 dark:text-gray-400 mt-1">
63
  {helpText}
64
- </div>
65
  )}
66
  </div>
67
  );
 
1
  'use client';
2
 
3
+ import {
4
+ Select,
5
+ SelectContent,
6
+ SelectItem,
7
+ SelectTrigger,
8
+ SelectValue,
9
+ } from '@/components/ui/select';
10
+ import { Label } from '@/components/ui/label';
11
+
12
  export interface SelectOption {
13
  value: string | number;
14
  label: string;
 
34
  onChange,
35
  className = '',
36
  disabled = false,
37
+ placeholder = 'Select an option',
38
  helpText,
39
  }: SelectInputProps) {
40
  const currentValue = value ?? defaultValue;
 
41
 
42
  return (
43
  <div className={className}>
44
+ <Label>
45
  {label}
46
+ </Label>
47
+ <Select
48
+ value={currentValue?.toString()}
49
+ onValueChange={(val) => {
50
+ const selectedOption = options.find(opt => opt.value.toString() === val);
51
  if (selectedOption) {
52
  onChange(selectedOption.value);
53
  }
54
  }}
55
  disabled={disabled}
 
56
  >
57
+ <SelectTrigger className="mt-2">
58
+ <SelectValue placeholder={placeholder} />
59
+ </SelectTrigger>
60
+ <SelectContent>
61
+ {options.map((option) => (
62
+ <SelectItem key={option.value.toString()} value={option.value.toString()}>
63
+ {option.label}
64
+ </SelectItem>
65
+ ))}
66
+ </SelectContent>
67
+ </Select>
68
  {helpText && (
69
+ <p className="text-xs text-muted-foreground mt-1">
70
  {helpText}
71
+ </p>
72
  )}
73
  </div>
74
  );
src/components/question-creation/inputs/TextInput.tsx CHANGED
@@ -1,5 +1,10 @@
1
  'use client';
2
 
 
 
 
 
 
3
  export interface TextInputProps {
4
  label: string;
5
  value?: string;
@@ -36,16 +41,15 @@ export default function TextInput({
36
  rows = 3,
37
  }: TextInputProps) {
38
  const currentValue = value ?? defaultValue;
39
- const baseClasses = "w-full p-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed";
40
 
41
  return (
42
  <div className={className}>
43
- <label className="block text-sm font-medium mb-2 text-gray-700 dark:text-gray-300">
44
  {label}
45
- {required && <span className="text-red-500 ml-1">*</span>}
46
- </label>
47
  {isTextarea ? (
48
- <textarea
49
  value={currentValue}
50
  placeholder={placeholder}
51
  onChange={(e) => onChange(e.target.value)}
@@ -54,10 +58,10 @@ export default function TextInput({
54
  maxLength={maxLength}
55
  minLength={minLength}
56
  rows={rows}
57
- className={`${baseClasses} bg-white dark:bg-gray-700 text-gray-900 dark:text-white border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400 resize-vertical`}
58
  />
59
  ) : (
60
- <input
61
  type={type}
62
  value={currentValue}
63
  placeholder={placeholder}
@@ -67,13 +71,13 @@ export default function TextInput({
67
  maxLength={maxLength}
68
  minLength={minLength}
69
  pattern={pattern}
70
- className={`${baseClasses} bg-white dark:bg-gray-700 text-gray-900 dark:text-white border-gray-300 dark:border-gray-600 placeholder-gray-500 dark:placeholder-gray-400`}
71
  />
72
  )}
73
  {helpText && (
74
- <div className="text-xs text-gray-500 dark:text-gray-400 mt-1">
75
  {helpText}
76
- </div>
77
  )}
78
  </div>
79
  );
 
1
  'use client';
2
 
3
+ import { Input } from '@/components/ui/input';
4
+ import { Textarea } from '@/components/ui/textarea';
5
+ import { Label } from '@/components/ui/label';
6
+ import { cn } from '@/lib/utils';
7
+
8
  export interface TextInputProps {
9
  label: string;
10
  value?: string;
 
41
  rows = 3,
42
  }: TextInputProps) {
43
  const currentValue = value ?? defaultValue;
 
44
 
45
  return (
46
  <div className={className}>
47
+ <Label>
48
  {label}
49
+ {required && <span className="text-destructive ml-1">*</span>}
50
+ </Label>
51
  {isTextarea ? (
52
+ <Textarea
53
  value={currentValue}
54
  placeholder={placeholder}
55
  onChange={(e) => onChange(e.target.value)}
 
58
  maxLength={maxLength}
59
  minLength={minLength}
60
  rows={rows}
61
+ className={cn("mt-2", disabled && "opacity-50 cursor-not-allowed")}
62
  />
63
  ) : (
64
+ <Input
65
  type={type}
66
  value={currentValue}
67
  placeholder={placeholder}
 
71
  maxLength={maxLength}
72
  minLength={minLength}
73
  pattern={pattern}
74
+ className={cn("mt-2", disabled && "opacity-50 cursor-not-allowed")}
75
  />
76
  )}
77
  {helpText && (
78
+ <p className="text-xs text-muted-foreground mt-1">
79
  {helpText}
80
+ </p>
81
  )}
82
  </div>
83
  );
src/components/question-output/QuestionCard.tsx CHANGED
@@ -1,6 +1,10 @@
1
  'use client';
2
 
3
  import { GeneratedQuestion, QuestionType } from '@/types/quiz';
 
 
 
 
4
 
5
  export interface QuestionCardProps {
6
  question: GeneratedQuestion;
@@ -72,20 +76,18 @@ export default function QuestionCard({
72
  };
73
 
74
  return (
75
- <div
76
  draggable
77
  onDragStart={handleDragStart}
78
  onDragEnd={handleDragEnd}
79
  onDragOver={handleDragOver}
80
  onDrop={handleDrop}
81
- className={`
82
- border border-gray-200 dark:border-gray-600 rounded-lg p-4
83
- hover:bg-gray-50 dark:hover:bg-gray-700 group
84
- transition-all duration-200 cursor-move
85
- ${isSelected ? 'ring-2 ring-blue-500 bg-blue-50 dark:bg-blue-900/20' : ''}
86
- ${isDragging ? 'opacity-50 scale-95 rotate-2' : ''}
87
- ${className}
88
- `}
89
  >
90
  <div className="flex items-start justify-between">
91
  <div className="flex items-start space-x-3 flex-1">
@@ -106,35 +108,34 @@ export default function QuestionCard({
106
 
107
  {/* Selection Checkbox */}
108
  {onSelect && (
109
- <input
110
- type="checkbox"
111
  checked={isSelected}
112
- onChange={handleSelect}
113
- className="mt-1 w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
114
  />
115
  )}
116
 
117
  {/* Question Content */}
118
  <div className="flex-1 min-w-0">
119
  <div className="flex items-center space-x-2 mb-2">
120
- <span className="text-sm font-medium text-blue-600 dark:text-blue-400">
121
  {questionType?.name || 'Unknown Type'}
122
  </span>
123
- <span className="text-xs text-gray-500 dark:text-gray-400">
124
  {question.points} pts
125
  </span>
126
- <span className="text-xs text-gray-400 dark:text-gray-500">
127
  {new Date(question.createdAt).toLocaleDateString()}
128
  </span>
129
  </div>
130
- <div className="text-gray-900 dark:text-white text-sm leading-relaxed">
131
  <p className="font-medium mb-2">{question.stem}</p>
132
 
133
  {/* Display Options */}
134
  {question.content && question.content.Options && (
135
  <div className="mt-3 space-y-1">
136
  {Object.entries(question.content.Options).map(([key, value]) => (
137
- <div key={key} className="text-xs text-gray-700 dark:text-gray-300">
138
  <span className="font-medium">{key})</span> {value as string}
139
  </div>
140
  ))}
@@ -154,46 +155,54 @@ export default function QuestionCard({
154
  {/* Action Buttons */}
155
  <div className="flex items-center space-x-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200 ml-2">
156
  {onEdit && (
157
- <button
158
  onClick={() => onEdit(question)}
159
- className="p-2 text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 rounded hover:bg-gray-100 dark:hover:bg-gray-600 transition-colors"
 
 
160
  title="Edit question"
161
  >
162
  <span className="text-sm">✏️</span>
163
- </button>
164
  )}
165
 
166
  {onDuplicate && (
167
- <button
168
  onClick={() => onDuplicate(question)}
169
- className="p-2 text-gray-400 hover:text-green-600 dark:hover:text-green-400 rounded hover:bg-gray-100 dark:hover:bg-gray-600 transition-colors"
 
 
170
  title="Duplicate question"
171
  >
172
  <span className="text-sm">📄</span>
173
- </button>
174
  )}
175
 
176
  {onPreview && (
177
- <button
178
  onClick={() => onPreview(question)}
179
- className="p-2 text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 rounded hover:bg-gray-100 dark:hover:bg-gray-600 transition-colors"
 
 
180
  title="Preview question"
181
  >
182
  <span className="text-sm">👁️</span>
183
- </button>
184
  )}
185
 
186
  {onRemove && (
187
- <button
188
  onClick={() => onRemove(question.id)}
189
- className="p-2 text-gray-400 hover:text-red-600 dark:hover:text-red-400 rounded hover:bg-gray-100 dark:hover:bg-gray-600 transition-colors"
 
 
190
  title="Remove question"
191
  >
192
  <span className="text-sm">✕</span>
193
- </button>
194
  )}
195
  </div>
196
  </div>
197
- </div>
198
  );
199
  }
 
1
  'use client';
2
 
3
  import { GeneratedQuestion, QuestionType } from '@/types/quiz';
4
+ import { Card } from '@/components/ui/card';
5
+ import { Button } from '@/components/ui/button';
6
+ import { Checkbox } from '@/components/ui/checkbox';
7
+ import { cn } from '@/lib/utils';
8
 
9
  export interface QuestionCardProps {
10
  question: GeneratedQuestion;
 
76
  };
77
 
78
  return (
79
+ <Card
80
  draggable
81
  onDragStart={handleDragStart}
82
  onDragEnd={handleDragEnd}
83
  onDragOver={handleDragOver}
84
  onDrop={handleDrop}
85
+ className={cn(
86
+ "p-4 hover:bg-accent group transition-all duration-200 cursor-move",
87
+ isSelected && "ring-2 ring-primary bg-primary/5",
88
+ isDragging && "opacity-50 scale-95 rotate-2",
89
+ className
90
+ )}
 
 
91
  >
92
  <div className="flex items-start justify-between">
93
  <div className="flex items-start space-x-3 flex-1">
 
108
 
109
  {/* Selection Checkbox */}
110
  {onSelect && (
111
+ <Checkbox
 
112
  checked={isSelected}
113
+ onCheckedChange={handleSelect}
114
+ className="mt-1"
115
  />
116
  )}
117
 
118
  {/* Question Content */}
119
  <div className="flex-1 min-w-0">
120
  <div className="flex items-center space-x-2 mb-2">
121
+ <span className="text-sm font-medium text-primary">
122
  {questionType?.name || 'Unknown Type'}
123
  </span>
124
+ <span className="text-xs text-muted-foreground">
125
  {question.points} pts
126
  </span>
127
+ <span className="text-xs text-muted-foreground">
128
  {new Date(question.createdAt).toLocaleDateString()}
129
  </span>
130
  </div>
131
+ <div className="text-foreground text-sm leading-relaxed">
132
  <p className="font-medium mb-2">{question.stem}</p>
133
 
134
  {/* Display Options */}
135
  {question.content && question.content.Options && (
136
  <div className="mt-3 space-y-1">
137
  {Object.entries(question.content.Options).map(([key, value]) => (
138
+ <div key={key} className="text-xs text-muted-foreground">
139
  <span className="font-medium">{key})</span> {value as string}
140
  </div>
141
  ))}
 
155
  {/* Action Buttons */}
156
  <div className="flex items-center space-x-1 opacity-0 group-hover:opacity-100 transition-opacity duration-200 ml-2">
157
  {onEdit && (
158
+ <Button
159
  onClick={() => onEdit(question)}
160
+ variant="ghost"
161
+ size="icon"
162
+ className="h-8 w-8"
163
  title="Edit question"
164
  >
165
  <span className="text-sm">✏️</span>
166
+ </Button>
167
  )}
168
 
169
  {onDuplicate && (
170
+ <Button
171
  onClick={() => onDuplicate(question)}
172
+ variant="ghost"
173
+ size="icon"
174
+ className="h-8 w-8"
175
  title="Duplicate question"
176
  >
177
  <span className="text-sm">📄</span>
178
+ </Button>
179
  )}
180
 
181
  {onPreview && (
182
+ <Button
183
  onClick={() => onPreview(question)}
184
+ variant="ghost"
185
+ size="icon"
186
+ className="h-8 w-8"
187
  title="Preview question"
188
  >
189
  <span className="text-sm">👁️</span>
190
+ </Button>
191
  )}
192
 
193
  {onRemove && (
194
+ <Button
195
  onClick={() => onRemove(question.id)}
196
+ variant="ghost"
197
+ size="icon"
198
+ className="h-8 w-8 hover:text-destructive"
199
  title="Remove question"
200
  >
201
  <span className="text-sm">✕</span>
202
+ </Button>
203
  )}
204
  </div>
205
  </div>
206
+ </Card>
207
  );
208
  }
src/components/question-output/QuestionList.tsx CHANGED
@@ -3,6 +3,12 @@
3
  import { useState } from 'react';
4
  import { GeneratedQuestion, QuestionType } from '@/types/quiz';
5
  import QuestionCard from './QuestionCard';
 
 
 
 
 
 
6
 
7
  export interface QuestionListProps {
8
  questions: GeneratedQuestion[];
@@ -38,6 +44,9 @@ export default function QuestionList({
38
  showCount = true,
39
  }: QuestionListProps) {
40
  const [draggedId, setDraggedId] = useState<string | null>(null);
 
 
 
41
 
42
  const handleSelectAll = () => {
43
  if (onQuestionSelect) {
@@ -75,36 +84,119 @@ export default function QuestionList({
75
  const someSelected = questions.some(q => selectedQuestions.has(q.id));
76
 
77
  return (
78
- <div className={`bg-white dark:bg-[#2c3034] ${className}`}>
79
- {/* Header */}
80
- <div className="p-4 border-b border-gray-200 dark:border-gray-600">
81
  <div className="flex items-center justify-between">
82
- <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
83
  🗂️ {title} {showCount && `(${questions.length})`}
84
- </h2>
85
 
86
- {/* Bulk Actions */}
87
- {questions.length > 0 && onQuestionSelect && (
88
- <div className="flex items-center space-x-2">
89
- <button
90
- onClick={handleSelectAll}
91
- className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
92
- >
93
- {allSelected ? 'Deselect All' : 'Select All'}
94
- </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
- {someSelected && (
97
- <span className="text-xs text-blue-600 dark:text-blue-400">
98
- {selectedQuestions.size} selected
99
- </span>
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  )}
101
  </div>
102
  )}
103
  </div>
104
- </div>
105
 
106
  {/* Content */}
107
- <div className="h-[calc(100%-80px)] overflow-y-auto p-4">
108
  {questions.length === 0 ? (
109
  <EmptyState message={emptyStateMessage} icon={emptyStateIcon} />
110
  ) : (
@@ -128,8 +220,8 @@ export default function QuestionList({
128
  ))}
129
  </div>
130
  )}
131
- </div>
132
- </div>
133
  );
134
  }
135
 
 
3
  import { useState } from 'react';
4
  import { GeneratedQuestion, QuestionType } from '@/types/quiz';
5
  import QuestionCard from './QuestionCard';
6
+ import { exportQuestionsToDocx } from '@/lib/exportUtils';
7
+ import { Button } from '@/components/ui/button';
8
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
9
+ import { Checkbox } from '@/components/ui/checkbox';
10
+ import { Label } from '@/components/ui/label';
11
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
12
 
13
  export interface QuestionListProps {
14
  questions: GeneratedQuestion[];
 
44
  showCount = true,
45
  }: QuestionListProps) {
46
  const [draggedId, setDraggedId] = useState<string | null>(null);
47
+ const [isExporting, setIsExporting] = useState(false);
48
+ const [includeAnswers, setIncludeAnswers] = useState(true);
49
+ const [exportFormat, setExportFormat] = useState<'docx' | 'txt'>('docx');
50
 
51
  const handleSelectAll = () => {
52
  if (onQuestionSelect) {
 
84
  const someSelected = questions.some(q => selectedQuestions.has(q.id));
85
 
86
  return (
87
+ <Card className={className}>
88
+ <CardHeader className="border-b">
 
89
  <div className="flex items-center justify-between">
90
+ <CardTitle className="text-lg font-semibold">
91
  🗂️ {title} {showCount && `(${questions.length})`}
92
+ </CardTitle>
93
 
94
+ {/* Export and Bulk Actions */}
95
+ {questions.length > 0 && (
96
+ <div className="flex items-center space-x-3">
97
+ {/* Export Options */}
98
+ <div className="flex items-center space-x-3">
99
+ {/* Format Selector */}
100
+ <Select value={exportFormat} onValueChange={(value) => setExportFormat(value as 'docx' | 'txt')}>
101
+ <SelectTrigger className="w-[100px]">
102
+ <SelectValue />
103
+ </SelectTrigger>
104
+ <SelectContent>
105
+ <SelectItem value="docx">DOCX</SelectItem>
106
+ <SelectItem value="txt">TXT</SelectItem>
107
+ </SelectContent>
108
+ </Select>
109
+
110
+ {/* Include Answers Toggle */}
111
+ <div className="flex items-center space-x-2">
112
+ <Checkbox
113
+ id="include-answers"
114
+ checked={includeAnswers}
115
+ onCheckedChange={(checked) => setIncludeAnswers(checked as boolean)}
116
+ />
117
+ <Label htmlFor="include-answers" className="text-sm cursor-pointer">
118
+ Include Answers
119
+ </Label>
120
+ </div>
121
+
122
+ {/* Export Button */}
123
+ <Button
124
+ onClick={async () => {
125
+ if (isExporting) return;
126
+
127
+ setIsExporting(true);
128
+ try {
129
+ const questionsToExport = someSelected && selectedQuestions.size > 0
130
+ ? questions.filter(q => selectedQuestions.has(q.id))
131
+ : questions;
132
+ const filename = someSelected && selectedQuestions.size > 0
133
+ ? `selected-questions-${selectedQuestions.size}${includeAnswers ? '-with-answers' : '-no-answers'}.${exportFormat}`
134
+ : `all-questions-${questions.length}${includeAnswers ? '-with-answers' : '-no-answers'}.${exportFormat}`;
135
+
136
+ // Debug: Log the first question structure
137
+ if (questionsToExport.length > 0) {
138
+ console.log('First question structure:', questionsToExport[0]);
139
+ console.log('First question content:', questionsToExport[0].content);
140
+ }
141
+
142
+ if (exportFormat === 'docx') {
143
+ await exportQuestionsToDocx(questionsToExport, filename, includeAnswers);
144
+ } else {
145
+ // For now, just show a message that TXT export is not implemented
146
+ alert('TXT export is not yet implemented. Please use DOCX format.');
147
+ }
148
+ } catch (error) {
149
+ console.error('Export failed:', error);
150
+ // You could add a toast notification here
151
+ } finally {
152
+ setIsExporting(false);
153
+ }
154
+ }}
155
+ disabled={isExporting}
156
+ variant="default"
157
+ size="sm"
158
+ title={someSelected && selectedQuestions.size > 0
159
+ ? `Export ${selectedQuestions.size} selected questions to ${exportFormat.toUpperCase()} file`
160
+ : `Export all questions to ${exportFormat.toUpperCase()} file`
161
+ }
162
+ >
163
+ <span>{isExporting ? '⏳' : '📄'}</span>
164
+ <span>
165
+ {isExporting
166
+ ? 'Exporting...'
167
+ : someSelected && selectedQuestions.size > 0
168
+ ? `Export Selected (${selectedQuestions.size})`
169
+ : `Export to ${exportFormat.toUpperCase()}`
170
+ }
171
+ </span>
172
+ </Button>
173
+ </div>
174
 
175
+ {/* Bulk Actions */}
176
+ {onQuestionSelect && (
177
+ <div className="flex items-center space-x-2">
178
+ <Button
179
+ onClick={handleSelectAll}
180
+ variant="ghost"
181
+ size="sm"
182
+ >
183
+ {allSelected ? 'Deselect All' : 'Select All'}
184
+ </Button>
185
+
186
+ {someSelected && (
187
+ <span className="text-xs text-primary">
188
+ {selectedQuestions.size} selected
189
+ </span>
190
+ )}
191
+ </div>
192
  )}
193
  </div>
194
  )}
195
  </div>
196
+ </CardHeader>
197
 
198
  {/* Content */}
199
+ <CardContent className="h-[calc(100%-80px)] overflow-y-auto p-4">
200
  {questions.length === 0 ? (
201
  <EmptyState message={emptyStateMessage} icon={emptyStateIcon} />
202
  ) : (
 
220
  ))}
221
  </div>
222
  )}
223
+ </CardContent>
224
+ </Card>
225
  );
226
  }
227
 
src/components/question-output/QuestionPreview.tsx CHANGED
@@ -1,6 +1,10 @@
1
  'use client';
2
 
3
  import { GeneratedQuestion, QuestionType } from '@/types/quiz';
 
 
 
 
4
 
5
  export interface QuestionPreviewProps {
6
  question: GeneratedQuestion;
@@ -80,20 +84,19 @@ export default function QuestionPreview({
80
  };
81
 
82
  return (
83
- <div className={`bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg ${className}`}>
84
- {/* Header */}
85
- <div className="p-4 border-b border-gray-200 dark:border-gray-700">
86
  <div className="flex items-start justify-between">
87
  <div>
88
  <div className="flex items-center space-x-2 mb-1">
89
- <span className="text-sm font-medium text-blue-600 dark:text-blue-400">
90
  {questionType?.name || 'Question'}
91
- </span>
92
- <span className="text-xs text-gray-500 dark:text-gray-400">
93
  {question.points} points
94
  </span>
95
  </div>
96
- <p className="text-xs text-gray-500 dark:text-gray-400">
97
  Created: {new Date(question.createdAt).toLocaleString()}
98
  </p>
99
  </div>
@@ -101,39 +104,44 @@ export default function QuestionPreview({
101
  {showActions && (
102
  <div className="flex items-center space-x-2">
103
  {onEdit && (
104
- <button
105
  onClick={() => onEdit(question)}
106
- className="px-3 py-1 text-sm text-blue-600 dark:text-blue-400 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded transition-colors"
 
107
  >
108
  Edit
109
- </button>
110
  )}
111
  {onDuplicate && (
112
- <button
113
  onClick={() => onDuplicate(question)}
114
- className="px-3 py-1 text-sm text-green-600 dark:text-green-400 hover:bg-green-50 dark:hover:bg-green-900/20 rounded transition-colors"
 
 
115
  >
116
  Duplicate
117
- </button>
118
  )}
119
  {onRemove && (
120
- <button
121
  onClick={() => onRemove(question.id)}
122
- className="px-3 py-1 text-sm text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors"
 
 
123
  >
124
  Remove
125
- </button>
126
  )}
127
  </div>
128
  )}
129
  </div>
130
- </div>
131
 
132
  {/* Content */}
133
- <div className="p-4">
134
  {renderQuestionContent()}
135
- </div>
136
- </div>
137
  );
138
  }
139
 
 
1
  'use client';
2
 
3
  import { GeneratedQuestion, QuestionType } from '@/types/quiz';
4
+ import { Card, CardContent, CardHeader } from '@/components/ui/card';
5
+ import { Button } from '@/components/ui/button';
6
+ import { Badge } from '@/components/ui/badge';
7
+ import { cn } from '@/lib/utils';
8
 
9
  export interface QuestionPreviewProps {
10
  question: GeneratedQuestion;
 
84
  };
85
 
86
  return (
87
+ <Card className={cn(className)}>
88
+ <CardHeader className="border-b">
 
89
  <div className="flex items-start justify-between">
90
  <div>
91
  <div className="flex items-center space-x-2 mb-1">
92
+ <Badge variant="default">
93
  {questionType?.name || 'Question'}
94
+ </Badge>
95
+ <span className="text-xs text-muted-foreground">
96
  {question.points} points
97
  </span>
98
  </div>
99
+ <p className="text-xs text-muted-foreground">
100
  Created: {new Date(question.createdAt).toLocaleString()}
101
  </p>
102
  </div>
 
104
  {showActions && (
105
  <div className="flex items-center space-x-2">
106
  {onEdit && (
107
+ <Button
108
  onClick={() => onEdit(question)}
109
+ variant="outline"
110
+ size="sm"
111
  >
112
  Edit
113
+ </Button>
114
  )}
115
  {onDuplicate && (
116
+ <Button
117
  onClick={() => onDuplicate(question)}
118
+ variant="outline"
119
+ size="sm"
120
+ className="text-green-600 hover:text-green-700"
121
  >
122
  Duplicate
123
+ </Button>
124
  )}
125
  {onRemove && (
126
+ <Button
127
  onClick={() => onRemove(question.id)}
128
+ variant="outline"
129
+ size="sm"
130
+ className="text-destructive hover:text-destructive"
131
  >
132
  Remove
133
+ </Button>
134
  )}
135
  </div>
136
  )}
137
  </div>
138
+ </CardHeader>
139
 
140
  {/* Content */}
141
+ <CardContent className="p-4">
142
  {renderQuestionContent()}
143
+ </CardContent>
144
+ </Card>
145
  );
146
  }
147
 
src/components/source-article/ArticleGenerationModal.tsx CHANGED
@@ -1,6 +1,20 @@
1
  'use client';
2
 
3
  import { useState, useEffect } from 'react';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
  interface ArticleGenerationModalProps {
6
  isOpen: boolean;
@@ -106,195 +120,189 @@ export function ArticleGenerationModal({
106
  onGenerate(formData);
107
  };
108
 
109
- if (!isOpen) return null;
110
-
111
  return (
112
- <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
113
- <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-4xl w-full max-h-[90vh] overflow-y-auto">
114
- <div className="p-6 border-b border-gray-200 dark:border-gray-600 flex justify-between items-center">
115
- <h2 className="text-xl font-semibold text-gray-900 dark:text-white">
116
- 📝 Generate Article
117
- </h2>
118
- <button
119
- onClick={onClose}
120
- className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
121
- >
122
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
123
- <line x1="18" y1="6" x2="6" y2="18"></line>
124
- <line x1="6" y1="6" x2="18" y2="18"></line>
125
- </svg>
126
- </button>
127
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
 
129
- <form onSubmit={handleSubmit} className="p-6 space-y-6">
130
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
131
- {/* Publisher */}
132
- <div>
133
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
134
- 出版社 (Publisher)
135
- </label>
136
- <div className="space-y-2">
137
- {PUBLISHER_OPTIONS.map(option => (
138
- <label key={option} className="flex items-center">
139
- <input
140
- type="checkbox"
141
- checked={formData.publisher.includes(option)}
142
- onChange={() => handleCheckboxChange('publisher', option)}
143
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
144
- />
145
- <span className="ml-2 text-sm text-gray-900 dark:text-gray-100">{option}</span>
146
- </label>
147
- ))}
 
148
  </div>
149
  </div>
150
 
151
- {/* Grade */}
152
  <div>
153
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
154
- 學生年級 (Grade Level)
155
- </label>
156
- <div className="space-y-2">
157
- {GRADE_OPTIONS.map(option => (
158
- <label key={option} className="flex items-center">
159
- <input
160
- type="checkbox"
161
- checked={formData.grade.includes(option)}
162
- onChange={() => handleCheckboxChange('grade', option)}
163
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
164
  />
165
- <span className="ml-2 text-sm text-gray-900 dark:text-gray-100">{option}</span>
166
- </label>
 
 
 
 
 
167
  ))}
168
  </div>
169
  </div>
170
- </div>
171
 
172
- {/* Unit */}
173
- <div>
174
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
175
- 程範圍 (Unit Range)
176
- </label>
177
- <div className="grid grid-cols-3 gap-2">
178
- {UNIT_OPTIONS.map(option => (
179
- <label key={option} className="flex items-center">
180
- <input
181
- type="checkbox"
182
- checked={formData.unit.includes(option)}
183
- onChange={() => handleCheckboxChange('unit', option)}
184
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
185
- />
186
- <span className="ml-2 text-sm text-gray-900 dark:text-gray-100">{option}</span>
187
- </label>
188
- ))}
189
  </div>
190
- </div>
191
 
192
- {/* Textbook Vocabulary */}
193
- <div>
194
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
195
- 課本單字列表 (Textbook Vocabulary)
196
- </label>
197
- <textarea
198
- value={formData.textbookVocab}
199
- readOnly
200
- placeholder="Select units to see vocabulary"
201
- className="w-full h-24 p-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-gray-100 text-sm"
202
- />
203
- </div>
204
 
205
- {/* Additional Vocabulary */}
206
- <div>
207
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
208
- 額外單字列表 (Additional Vocabulary)
209
- </label>
210
- <textarea
211
- value={formData.additionalVocab}
212
- onChange={(e) => handleTextChange('additionalVocab', e.target.value)}
213
- placeholder="Enter additional vocabulary words, separated by commas"
214
- className="w-full h-24 p-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-gray-100"
215
- />
216
- </div>
 
 
 
 
 
 
 
 
 
 
217
 
218
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
219
- {/* Grammar */}
220
- <div>
221
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
222
- 文法範圍 (Grammar Focus)
223
- </label>
224
- <div className="space-y-2">
225
- {GRAMMAR_OPTIONS.map(option => (
226
- <label key={option} className="flex items-center">
227
- <input
228
- type="checkbox"
229
- checked={formData.grammar.includes(option)}
230
- onChange={() => handleCheckboxChange('grammar', option)}
231
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
232
- />
233
- <span className="ml-2 text-sm text-gray-900 dark:text-gray-100">{option}</span>
234
- </label>
235
- ))}
 
 
236
  </div>
237
  </div>
238
 
239
- {/* Topic */}
240
  <div>
241
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
242
- 主題範圍 (Topic)
243
- </label>
244
- <div className="space-y-2">
245
- {TOPIC_OPTIONS.map(option => (
246
- <label key={option} className="flex items-center">
247
- <input
248
- type="checkbox"
249
- checked={formData.topic.includes(option)}
250
- onChange={() => handleCheckboxChange('topic', option)}
251
- className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
252
- />
253
- <span className="ml-2 text-sm text-gray-900 dark:text-gray-100">{option}</span>
254
- </label>
255
- ))}
256
- </div>
257
  </div>
258
- </div>
 
259
 
260
- {/* Input Article */}
261
- <div>
262
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
263
- 初始文章 (Initial Article)
264
- </label>
265
- <textarea
266
- value={formData.inputArticle}
267
- onChange={(e) => handleTextChange('inputArticle', e.target.value)}
268
- placeholder="Enter an initial article or topic to base the generation on..."
269
- className="w-full h-32 p-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-gray-100"
270
- />
271
- </div>
272
-
273
- {/* Buttons */}
274
- <div className="flex justify-end space-x-3 pt-4 border-t border-gray-200 dark:border-gray-600">
275
- <button
276
- type="button"
277
- onClick={onClose}
278
- className="px-4 py-2 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700"
279
- >
280
- Cancel
281
- </button>
282
- <button
283
- type="submit"
284
- disabled={isGenerating}
285
- className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:bg-blue-400 disabled:cursor-not-allowed flex items-center space-x-2"
286
- >
287
- {isGenerating && (
288
- <svg className="animate-spin h-4 w-4" viewBox="0 0 24 24">
289
- <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
290
- <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 0 1 8-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 0 1 4 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
291
- </svg>
292
- )}
293
- <span>{isGenerating ? '生成中...' : '生成初始文章'}</span>
294
- </button>
295
- </div>
296
- </form>
297
- </div>
298
- </div>
299
  );
300
  }
 
1
  'use client';
2
 
3
  import { useState, useEffect } from 'react';
4
+ import {
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogFooter,
11
+ } from '@/components/ui/dialog';
12
+ import { Button } from '@/components/ui/button';
13
+ import { Checkbox } from '@/components/ui/checkbox';
14
+ import { Label } from '@/components/ui/label';
15
+ import { Textarea } from '@/components/ui/textarea';
16
+ import { ScrollArea } from '@/components/ui/scroll-area';
17
+ import { Loader2 } from 'lucide-react';
18
 
19
  interface ArticleGenerationModalProps {
20
  isOpen: boolean;
 
120
  onGenerate(formData);
121
  };
122
 
 
 
123
  return (
124
+ <Dialog open={isOpen} onOpenChange={onClose}>
125
+ <DialogContent className="max-w-4xl max-h-[90vh]">
126
+ <DialogHeader>
127
+ <DialogTitle>📝 Generate Article</DialogTitle>
128
+ <DialogDescription>
129
+ Configure the parameters for article generation
130
+ </DialogDescription>
131
+ </DialogHeader>
132
+
133
+ <ScrollArea className="h-[calc(90vh-200px)] pr-4">
134
+ <form onSubmit={handleSubmit} className="space-y-6">
135
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
136
+ {/* Publisher */}
137
+ <div>
138
+ <Label className="mb-2">出版社 (Publisher)</Label>
139
+ <div className="space-y-2">
140
+ {PUBLISHER_OPTIONS.map(option => (
141
+ <div key={option} className="flex items-center space-x-2">
142
+ <Checkbox
143
+ id={`publisher-${option}`}
144
+ checked={formData.publisher.includes(option)}
145
+ onCheckedChange={() => handleCheckboxChange('publisher', option)}
146
+ />
147
+ <Label
148
+ htmlFor={`publisher-${option}`}
149
+ className="text-sm font-normal cursor-pointer"
150
+ >
151
+ {option}
152
+ </Label>
153
+ </div>
154
+ ))}
155
+ </div>
156
+ </div>
157
 
158
+ {/* Grade */}
159
+ <div>
160
+ <Label className="mb-2">學生年級 (Grade Level)</Label>
161
+ <div className="space-y-2">
162
+ {GRADE_OPTIONS.map(option => (
163
+ <div key={option} className="flex items-center space-x-2">
164
+ <Checkbox
165
+ id={`grade-${option}`}
166
+ checked={formData.grade.includes(option)}
167
+ onCheckedChange={() => handleCheckboxChange('grade', option)}
168
+ />
169
+ <Label
170
+ htmlFor={`grade-${option}`}
171
+ className="text-sm font-normal cursor-pointer"
172
+ >
173
+ {option}
174
+ </Label>
175
+ </div>
176
+ ))}
177
+ </div>
178
  </div>
179
  </div>
180
 
181
+ {/* Unit */}
182
  <div>
183
+ <Label className="mb-2">課程範圍 (Unit Range)</Label>
184
+ <div className="grid grid-cols-3 gap-2">
185
+ {UNIT_OPTIONS.map(option => (
186
+ <div key={option} className="flex items-center space-x-2">
187
+ <Checkbox
188
+ id={`unit-${option}`}
189
+ checked={formData.unit.includes(option)}
190
+ onCheckedChange={() => handleCheckboxChange('unit', option)}
 
 
 
191
  />
192
+ <Label
193
+ htmlFor={`unit-${option}`}
194
+ className="text-sm font-normal cursor-pointer"
195
+ >
196
+ {option}
197
+ </Label>
198
+ </div>
199
  ))}
200
  </div>
201
  </div>
 
202
 
203
+ {/* Textbook Vocabulary */}
204
+ <div>
205
+ <Label htmlFor="textbook-vocab" className="mb-2">
206
+ 本單字列表 (Textbook Vocabulary)
207
+ </Label>
208
+ <Textarea
209
+ id="textbook-vocab"
210
+ value={formData.textbookVocab}
211
+ readOnly
212
+ placeholder="Select units to see vocabulary"
213
+ className="bg-muted"
214
+ />
 
 
 
 
 
215
  </div>
 
216
 
217
+ {/* Additional Vocabulary */}
218
+ <div>
219
+ <Label htmlFor="additional-vocab" className="mb-2">
220
+ 額外單字列表 (Additional Vocabulary)
221
+ </Label>
222
+ <Textarea
223
+ id="additional-vocab"
224
+ value={formData.additionalVocab}
225
+ onChange={(e) => handleTextChange('additionalVocab', e.target.value)}
226
+ placeholder="Enter additional vocabulary words, separated by commas"
227
+ />
228
+ </div>
229
 
230
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
231
+ {/* Grammar */}
232
+ <div>
233
+ <Label className="mb-2">文法範圍 (Grammar Focus)</Label>
234
+ <div className="space-y-2">
235
+ {GRAMMAR_OPTIONS.map(option => (
236
+ <div key={option} className="flex items-center space-x-2">
237
+ <Checkbox
238
+ id={`grammar-${option}`}
239
+ checked={formData.grammar.includes(option)}
240
+ onCheckedChange={() => handleCheckboxChange('grammar', option)}
241
+ />
242
+ <Label
243
+ htmlFor={`grammar-${option}`}
244
+ className="text-sm font-normal cursor-pointer"
245
+ >
246
+ {option}
247
+ </Label>
248
+ </div>
249
+ ))}
250
+ </div>
251
+ </div>
252
 
253
+ {/* Topic */}
254
+ <div>
255
+ <Label className="mb-2">主題範圍 (Topic)</Label>
256
+ <div className="space-y-2">
257
+ {TOPIC_OPTIONS.map(option => (
258
+ <div key={option} className="flex items-center space-x-2">
259
+ <Checkbox
260
+ id={`topic-${option}`}
261
+ checked={formData.topic.includes(option)}
262
+ onCheckedChange={() => handleCheckboxChange('topic', option)}
263
+ />
264
+ <Label
265
+ htmlFor={`topic-${option}`}
266
+ className="text-sm font-normal cursor-pointer"
267
+ >
268
+ {option}
269
+ </Label>
270
+ </div>
271
+ ))}
272
+ </div>
273
  </div>
274
  </div>
275
 
276
+ {/* Input Article */}
277
  <div>
278
+ <Label htmlFor="input-article" className="mb-2">
279
+ 初始文章 (Initial Article)
280
+ </Label>
281
+ <Textarea
282
+ id="input-article"
283
+ value={formData.inputArticle}
284
+ onChange={(e) => handleTextChange('inputArticle', e.target.value)}
285
+ placeholder="Enter an initial article or topic to base the generation on..."
286
+ className="min-h-[120px]"
287
+ />
 
 
 
 
 
 
288
  </div>
289
+ </form>
290
+ </ScrollArea>
291
 
292
+ <DialogFooter>
293
+ <Button type="button" variant="outline" onClick={onClose}>
294
+ Cancel
295
+ </Button>
296
+ <Button
297
+ type="submit"
298
+ onClick={handleSubmit}
299
+ disabled={isGenerating}
300
+ >
301
+ {isGenerating && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
302
+ {isGenerating ? '生成中...' : '生成初始文章'}
303
+ </Button>
304
+ </DialogFooter>
305
+ </DialogContent>
306
+ </Dialog>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  );
308
  }
src/components/source-article/SourceArticle.tsx CHANGED
@@ -2,6 +2,11 @@
2
 
3
  import { useState, useEffect } from 'react';
4
  import { ArticleGenerationModal, ArticleGenerationParams } from './ArticleGenerationModal';
 
 
 
 
 
5
 
6
  interface SourceArticleProps {
7
  className?: string;
@@ -62,44 +67,44 @@ export function SourceArticle({
62
  };
63
 
64
  return (
65
- <div className={`bg-white dark:bg-[#2c3034] border-b border-gray-200 dark:border-gray-600 ${className}`}>
66
- <div className="p-4 border-b border-gray-200 dark:border-gray-600 flex justify-between items-center">
67
- <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">
68
  📄 Source Article
69
- </h2>
70
  <div className="flex items-center space-x-4">
71
- <button
72
  onClick={() => setIsModalOpen(true)}
73
  disabled={isSourceLocked}
74
- className="px-3 py-1.5 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed flex items-center space-x-1"
75
  >
76
- <span></span>
77
- <span>Generate</span>
78
- </button>
79
- <span className="text-sm text-gray-500 dark:text-gray-400">
80
  {wordCount} words
81
  </span>
82
- <label className="flex items-center space-x-2">
83
- <input
84
- type="checkbox"
85
  checked={isSourceLocked}
86
- onChange={(e) => onSourceLockedChange(e.target.checked)}
87
- className="rounded"
88
  />
89
- <span className="text-sm">🔒 Lock</span>
90
- </label>
 
 
91
  </div>
92
- </div>
93
 
94
- <div className="h-[calc(100%-80px)] p-4">
95
- <textarea
96
  value={sourceArticle}
97
  onChange={(e) => handleSourceArticleChange(e.target.value)}
98
  placeholder="Paste or type your source article here (articles, passages, etc.)..."
99
  disabled={isSourceLocked}
100
- className="w-full h-full resize-none border border-gray-300 dark:border-gray-500 rounded-lg p-4 focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-gray-100 disabled:bg-gray-100 dark:disabled:bg-gray-600"
101
  />
102
- </div>
103
 
104
  <ArticleGenerationModal
105
  isOpen={isModalOpen}
@@ -107,6 +112,6 @@ export function SourceArticle({
107
  onGenerate={handleGenerateArticle}
108
  isGenerating={isGeneratingArticle}
109
  />
110
- </div>
111
  );
112
  }
 
2
 
3
  import { useState, useEffect } from 'react';
4
  import { ArticleGenerationModal, ArticleGenerationParams } from './ArticleGenerationModal';
5
+ import { Button } from '@/components/ui/button';
6
+ import { Checkbox } from '@/components/ui/checkbox';
7
+ import { Label } from '@/components/ui/label';
8
+ import { Textarea } from '@/components/ui/textarea';
9
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
10
 
11
  interface SourceArticleProps {
12
  className?: string;
 
67
  };
68
 
69
  return (
70
+ <Card className={`border-b ${className}`}>
71
+ <CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
72
+ <CardTitle className="text-lg font-semibold">
73
  📄 Source Article
74
+ </CardTitle>
75
  <div className="flex items-center space-x-4">
76
+ <Button
77
  onClick={() => setIsModalOpen(true)}
78
  disabled={isSourceLocked}
79
+ size="sm"
80
  >
81
+ Generate
82
+ </Button>
83
+ <span className="text-sm text-muted-foreground">
 
84
  {wordCount} words
85
  </span>
86
+ <div className="flex items-center space-x-2">
87
+ <Checkbox
88
+ id="lock-source"
89
  checked={isSourceLocked}
90
+ onCheckedChange={onSourceLockedChange}
 
91
  />
92
+ <Label htmlFor="lock-source" className="text-sm cursor-pointer">
93
+ 🔒 Lock
94
+ </Label>
95
+ </div>
96
  </div>
97
+ </CardHeader>
98
 
99
+ <CardContent className="h-[calc(100%-80px)]">
100
+ <Textarea
101
  value={sourceArticle}
102
  onChange={(e) => handleSourceArticleChange(e.target.value)}
103
  placeholder="Paste or type your source article here (articles, passages, etc.)..."
104
  disabled={isSourceLocked}
105
+ className="w-full h-full resize-none min-h-[300px]"
106
  />
107
+ </CardContent>
108
 
109
  <ArticleGenerationModal
110
  isOpen={isModalOpen}
 
112
  onGenerate={handleGenerateArticle}
113
  isGenerating={isGeneratingArticle}
114
  />
115
+ </Card>
116
  );
117
  }
src/components/ui/badge.tsx ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ const badgeVariants = cva(
7
+ "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default:
12
+ "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
13
+ secondary:
14
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15
+ destructive:
16
+ "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
17
+ outline: "text-foreground",
18
+ },
19
+ },
20
+ defaultVariants: {
21
+ variant: "default",
22
+ },
23
+ }
24
+ )
25
+
26
+ export interface BadgeProps
27
+ extends React.HTMLAttributes<HTMLDivElement>,
28
+ VariantProps<typeof badgeVariants> {}
29
+
30
+ function Badge({ className, variant, ...props }: BadgeProps) {
31
+ return (
32
+ <div className={cn(badgeVariants({ variant }), className)} {...props} />
33
+ )
34
+ }
35
+
36
+ export { Badge, badgeVariants }
src/components/ui/button.tsx ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+ import { Slot } from "@radix-ui/react-slot"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ const buttonVariants = cva(
8
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
14
+ destructive:
15
+ "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
16
+ outline:
17
+ "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
18
+ secondary:
19
+ "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
20
+ ghost:
21
+ "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
22
+ link: "text-primary underline-offset-4 hover:underline",
23
+ },
24
+ size: {
25
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
26
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
27
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
28
+ icon: "size-9",
29
+ },
30
+ },
31
+ defaultVariants: {
32
+ variant: "default",
33
+ size: "default",
34
+ },
35
+ }
36
+ )
37
+
38
+ function Button({
39
+ className,
40
+ variant,
41
+ size,
42
+ asChild = false,
43
+ ...props
44
+ }: React.ComponentProps<"button"> &
45
+ VariantProps<typeof buttonVariants> & {
46
+ asChild?: boolean
47
+ }) {
48
+ const Comp = asChild ? Slot : "button"
49
+
50
+ return (
51
+ <Comp
52
+ data-slot="button"
53
+ className={cn(buttonVariants({ variant, size, className }))}
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ export { Button, buttonVariants }
src/components/ui/card.tsx ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Card({ className, ...props }: React.ComponentProps<"div">) {
6
+ return (
7
+ <div
8
+ data-slot="card"
9
+ className={cn(
10
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
11
+ className
12
+ )}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
19
+ return (
20
+ <div
21
+ data-slot="card-header"
22
+ className={cn(
23
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
24
+ className
25
+ )}
26
+ {...props}
27
+ />
28
+ )
29
+ }
30
+
31
+ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
32
+ return (
33
+ <div
34
+ data-slot="card-title"
35
+ className={cn("leading-none font-semibold", className)}
36
+ {...props}
37
+ />
38
+ )
39
+ }
40
+
41
+ function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
42
+ return (
43
+ <div
44
+ data-slot="card-description"
45
+ className={cn("text-muted-foreground text-sm", className)}
46
+ {...props}
47
+ />
48
+ )
49
+ }
50
+
51
+ function CardAction({ className, ...props }: React.ComponentProps<"div">) {
52
+ return (
53
+ <div
54
+ data-slot="card-action"
55
+ className={cn(
56
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
57
+ className
58
+ )}
59
+ {...props}
60
+ />
61
+ )
62
+ }
63
+
64
+ function CardContent({ className, ...props }: React.ComponentProps<"div">) {
65
+ return (
66
+ <div
67
+ data-slot="card-content"
68
+ className={cn("px-6", className)}
69
+ {...props}
70
+ />
71
+ )
72
+ }
73
+
74
+ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
75
+ return (
76
+ <div
77
+ data-slot="card-footer"
78
+ className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
79
+ {...props}
80
+ />
81
+ )
82
+ }
83
+
84
+ export {
85
+ Card,
86
+ CardHeader,
87
+ CardFooter,
88
+ CardTitle,
89
+ CardAction,
90
+ CardDescription,
91
+ CardContent,
92
+ }
src/components/ui/checkbox.tsx ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
5
+ import { CheckIcon } from "lucide-react"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ function Checkbox({
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
13
+ return (
14
+ <CheckboxPrimitive.Root
15
+ data-slot="checkbox"
16
+ className={cn(
17
+ "peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
18
+ className
19
+ )}
20
+ {...props}
21
+ >
22
+ <CheckboxPrimitive.Indicator
23
+ data-slot="checkbox-indicator"
24
+ className="flex items-center justify-center text-current transition-none"
25
+ >
26
+ <CheckIcon className="size-3.5" />
27
+ </CheckboxPrimitive.Indicator>
28
+ </CheckboxPrimitive.Root>
29
+ )
30
+ }
31
+
32
+ export { Checkbox }
src/components/ui/dialog.tsx ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as DialogPrimitive from "@radix-ui/react-dialog"
5
+ import { XIcon } from "lucide-react"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ function Dialog({
10
+ ...props
11
+ }: React.ComponentProps<typeof DialogPrimitive.Root>) {
12
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />
13
+ }
14
+
15
+ function DialogTrigger({
16
+ ...props
17
+ }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
18
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
19
+ }
20
+
21
+ function DialogPortal({
22
+ ...props
23
+ }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
24
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
25
+ }
26
+
27
+ function DialogClose({
28
+ ...props
29
+ }: React.ComponentProps<typeof DialogPrimitive.Close>) {
30
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
31
+ }
32
+
33
+ function DialogOverlay({
34
+ className,
35
+ ...props
36
+ }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
37
+ return (
38
+ <DialogPrimitive.Overlay
39
+ data-slot="dialog-overlay"
40
+ className={cn(
41
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
42
+ className
43
+ )}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ function DialogContent({
50
+ className,
51
+ children,
52
+ showCloseButton = true,
53
+ ...props
54
+ }: React.ComponentProps<typeof DialogPrimitive.Content> & {
55
+ showCloseButton?: boolean
56
+ }) {
57
+ return (
58
+ <DialogPortal data-slot="dialog-portal">
59
+ <DialogOverlay />
60
+ <DialogPrimitive.Content
61
+ data-slot="dialog-content"
62
+ className={cn(
63
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
64
+ className
65
+ )}
66
+ {...props}
67
+ >
68
+ {children}
69
+ {showCloseButton && (
70
+ <DialogPrimitive.Close
71
+ data-slot="dialog-close"
72
+ className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
73
+ >
74
+ <XIcon />
75
+ <span className="sr-only">Close</span>
76
+ </DialogPrimitive.Close>
77
+ )}
78
+ </DialogPrimitive.Content>
79
+ </DialogPortal>
80
+ )
81
+ }
82
+
83
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
84
+ return (
85
+ <div
86
+ data-slot="dialog-header"
87
+ className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
88
+ {...props}
89
+ />
90
+ )
91
+ }
92
+
93
+ function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
94
+ return (
95
+ <div
96
+ data-slot="dialog-footer"
97
+ className={cn(
98
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
99
+ className
100
+ )}
101
+ {...props}
102
+ />
103
+ )
104
+ }
105
+
106
+ function DialogTitle({
107
+ className,
108
+ ...props
109
+ }: React.ComponentProps<typeof DialogPrimitive.Title>) {
110
+ return (
111
+ <DialogPrimitive.Title
112
+ data-slot="dialog-title"
113
+ className={cn("text-lg leading-none font-semibold", className)}
114
+ {...props}
115
+ />
116
+ )
117
+ }
118
+
119
+ function DialogDescription({
120
+ className,
121
+ ...props
122
+ }: React.ComponentProps<typeof DialogPrimitive.Description>) {
123
+ return (
124
+ <DialogPrimitive.Description
125
+ data-slot="dialog-description"
126
+ className={cn("text-muted-foreground text-sm", className)}
127
+ {...props}
128
+ />
129
+ )
130
+ }
131
+
132
+ export {
133
+ Dialog,
134
+ DialogClose,
135
+ DialogContent,
136
+ DialogDescription,
137
+ DialogFooter,
138
+ DialogHeader,
139
+ DialogOverlay,
140
+ DialogPortal,
141
+ DialogTitle,
142
+ DialogTrigger,
143
+ }
src/components/ui/form.tsx ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as LabelPrimitive from "@radix-ui/react-label"
5
+ import { Slot } from "@radix-ui/react-slot"
6
+ import {
7
+ Controller,
8
+ FormProvider,
9
+ useFormContext,
10
+ useFormState,
11
+ type ControllerProps,
12
+ type FieldPath,
13
+ type FieldValues,
14
+ } from "react-hook-form"
15
+
16
+ import { cn } from "@/lib/utils"
17
+ import { Label } from "@/components/ui/label"
18
+
19
+ const Form = FormProvider
20
+
21
+ type FormFieldContextValue<
22
+ TFieldValues extends FieldValues = FieldValues,
23
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
24
+ > = {
25
+ name: TName
26
+ }
27
+
28
+ const FormFieldContext = React.createContext<FormFieldContextValue>(
29
+ {} as FormFieldContextValue
30
+ )
31
+
32
+ const FormField = <
33
+ TFieldValues extends FieldValues = FieldValues,
34
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
35
+ >({
36
+ ...props
37
+ }: ControllerProps<TFieldValues, TName>) => {
38
+ return (
39
+ <FormFieldContext.Provider value={{ name: props.name }}>
40
+ <Controller {...props} />
41
+ </FormFieldContext.Provider>
42
+ )
43
+ }
44
+
45
+ const useFormField = () => {
46
+ const fieldContext = React.useContext(FormFieldContext)
47
+ const itemContext = React.useContext(FormItemContext)
48
+ const { getFieldState } = useFormContext()
49
+ const formState = useFormState({ name: fieldContext.name })
50
+ const fieldState = getFieldState(fieldContext.name, formState)
51
+
52
+ if (!fieldContext) {
53
+ throw new Error("useFormField should be used within <FormField>")
54
+ }
55
+
56
+ const { id } = itemContext
57
+
58
+ return {
59
+ id,
60
+ name: fieldContext.name,
61
+ formItemId: `${id}-form-item`,
62
+ formDescriptionId: `${id}-form-item-description`,
63
+ formMessageId: `${id}-form-item-message`,
64
+ ...fieldState,
65
+ }
66
+ }
67
+
68
+ type FormItemContextValue = {
69
+ id: string
70
+ }
71
+
72
+ const FormItemContext = React.createContext<FormItemContextValue>(
73
+ {} as FormItemContextValue
74
+ )
75
+
76
+ function FormItem({ className, ...props }: React.ComponentProps<"div">) {
77
+ const id = React.useId()
78
+
79
+ return (
80
+ <FormItemContext.Provider value={{ id }}>
81
+ <div
82
+ data-slot="form-item"
83
+ className={cn("grid gap-2", className)}
84
+ {...props}
85
+ />
86
+ </FormItemContext.Provider>
87
+ )
88
+ }
89
+
90
+ function FormLabel({
91
+ className,
92
+ ...props
93
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
94
+ const { error, formItemId } = useFormField()
95
+
96
+ return (
97
+ <Label
98
+ data-slot="form-label"
99
+ data-error={!!error}
100
+ className={cn("data-[error=true]:text-destructive", className)}
101
+ htmlFor={formItemId}
102
+ {...props}
103
+ />
104
+ )
105
+ }
106
+
107
+ function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
108
+ const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
109
+
110
+ return (
111
+ <Slot
112
+ data-slot="form-control"
113
+ id={formItemId}
114
+ aria-describedby={
115
+ !error
116
+ ? `${formDescriptionId}`
117
+ : `${formDescriptionId} ${formMessageId}`
118
+ }
119
+ aria-invalid={!!error}
120
+ {...props}
121
+ />
122
+ )
123
+ }
124
+
125
+ function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
126
+ const { formDescriptionId } = useFormField()
127
+
128
+ return (
129
+ <p
130
+ data-slot="form-description"
131
+ id={formDescriptionId}
132
+ className={cn("text-muted-foreground text-sm", className)}
133
+ {...props}
134
+ />
135
+ )
136
+ }
137
+
138
+ function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
139
+ const { error, formMessageId } = useFormField()
140
+ const body = error ? String(error?.message ?? "") : props.children
141
+
142
+ if (!body) {
143
+ return null
144
+ }
145
+
146
+ return (
147
+ <p
148
+ data-slot="form-message"
149
+ id={formMessageId}
150
+ className={cn("text-destructive text-sm", className)}
151
+ {...props}
152
+ >
153
+ {body}
154
+ </p>
155
+ )
156
+ }
157
+
158
+ export {
159
+ useFormField,
160
+ Form,
161
+ FormItem,
162
+ FormLabel,
163
+ FormControl,
164
+ FormDescription,
165
+ FormMessage,
166
+ FormField,
167
+ }
src/components/ui/input.tsx ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
6
+ return (
7
+ <input
8
+ type={type}
9
+ data-slot="input"
10
+ className={cn(
11
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
13
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ )
19
+ }
20
+
21
+ export { Input }
src/components/ui/label.tsx ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as LabelPrimitive from "@radix-ui/react-label"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function Label({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
12
+ return (
13
+ <LabelPrimitive.Root
14
+ data-slot="label"
15
+ className={cn(
16
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ )
22
+ }
23
+
24
+ export { Label }
src/components/ui/scroll-area.tsx ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ const ScrollArea = React.forwardRef<
9
+ React.ElementRef<typeof ScrollAreaPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
11
+ >(({ className, children, ...props }, ref) => (
12
+ <ScrollAreaPrimitive.Root
13
+ ref={ref}
14
+ className={cn("relative overflow-hidden", className)}
15
+ {...props}
16
+ >
17
+ <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
18
+ {children}
19
+ </ScrollAreaPrimitive.Viewport>
20
+ <ScrollBar />
21
+ <ScrollAreaPrimitive.Corner />
22
+ </ScrollAreaPrimitive.Root>
23
+ ))
24
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
25
+
26
+ const ScrollBar = React.forwardRef<
27
+ React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
28
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
29
+ >(({ className, orientation = "vertical", ...props }, ref) => (
30
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
31
+ ref={ref}
32
+ orientation={orientation}
33
+ className={cn(
34
+ "flex touch-none select-none transition-colors",
35
+ orientation === "vertical" &&
36
+ "h-full w-2.5 border-l border-l-transparent p-[1px]",
37
+ orientation === "horizontal" &&
38
+ "h-2.5 flex-col border-t border-t-transparent p-[1px]",
39
+ className
40
+ )}
41
+ {...props}
42
+ >
43
+ <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
44
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
45
+ ))
46
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
47
+
48
+ export { ScrollArea, ScrollBar }
src/components/ui/select.tsx ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as SelectPrimitive from "@radix-ui/react-select"
5
+ import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ function Select({
10
+ ...props
11
+ }: React.ComponentProps<typeof SelectPrimitive.Root>) {
12
+ return <SelectPrimitive.Root data-slot="select" {...props} />
13
+ }
14
+
15
+ function SelectGroup({
16
+ ...props
17
+ }: React.ComponentProps<typeof SelectPrimitive.Group>) {
18
+ return <SelectPrimitive.Group data-slot="select-group" {...props} />
19
+ }
20
+
21
+ function SelectValue({
22
+ ...props
23
+ }: React.ComponentProps<typeof SelectPrimitive.Value>) {
24
+ return <SelectPrimitive.Value data-slot="select-value" {...props} />
25
+ }
26
+
27
+ function SelectTrigger({
28
+ className,
29
+ size = "default",
30
+ children,
31
+ ...props
32
+ }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
33
+ size?: "sm" | "default"
34
+ }) {
35
+ return (
36
+ <SelectPrimitive.Trigger
37
+ data-slot="select-trigger"
38
+ data-size={size}
39
+ className={cn(
40
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
41
+ className
42
+ )}
43
+ {...props}
44
+ >
45
+ {children}
46
+ <SelectPrimitive.Icon asChild>
47
+ <ChevronDownIcon className="size-4 opacity-50" />
48
+ </SelectPrimitive.Icon>
49
+ </SelectPrimitive.Trigger>
50
+ )
51
+ }
52
+
53
+ function SelectContent({
54
+ className,
55
+ children,
56
+ position = "popper",
57
+ ...props
58
+ }: React.ComponentProps<typeof SelectPrimitive.Content>) {
59
+ return (
60
+ <SelectPrimitive.Portal>
61
+ <SelectPrimitive.Content
62
+ data-slot="select-content"
63
+ className={cn(
64
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
65
+ position === "popper" &&
66
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
67
+ className
68
+ )}
69
+ position={position}
70
+ {...props}
71
+ >
72
+ <SelectScrollUpButton />
73
+ <SelectPrimitive.Viewport
74
+ className={cn(
75
+ "p-1",
76
+ position === "popper" &&
77
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
78
+ )}
79
+ >
80
+ {children}
81
+ </SelectPrimitive.Viewport>
82
+ <SelectScrollDownButton />
83
+ </SelectPrimitive.Content>
84
+ </SelectPrimitive.Portal>
85
+ )
86
+ }
87
+
88
+ function SelectLabel({
89
+ className,
90
+ ...props
91
+ }: React.ComponentProps<typeof SelectPrimitive.Label>) {
92
+ return (
93
+ <SelectPrimitive.Label
94
+ data-slot="select-label"
95
+ className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
96
+ {...props}
97
+ />
98
+ )
99
+ }
100
+
101
+ function SelectItem({
102
+ className,
103
+ children,
104
+ ...props
105
+ }: React.ComponentProps<typeof SelectPrimitive.Item>) {
106
+ return (
107
+ <SelectPrimitive.Item
108
+ data-slot="select-item"
109
+ className={cn(
110
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
111
+ className
112
+ )}
113
+ {...props}
114
+ >
115
+ <span className="absolute right-2 flex size-3.5 items-center justify-center">
116
+ <SelectPrimitive.ItemIndicator>
117
+ <CheckIcon className="size-4" />
118
+ </SelectPrimitive.ItemIndicator>
119
+ </span>
120
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
121
+ </SelectPrimitive.Item>
122
+ )
123
+ }
124
+
125
+ function SelectSeparator({
126
+ className,
127
+ ...props
128
+ }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
129
+ return (
130
+ <SelectPrimitive.Separator
131
+ data-slot="select-separator"
132
+ className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
133
+ {...props}
134
+ />
135
+ )
136
+ }
137
+
138
+ function SelectScrollUpButton({
139
+ className,
140
+ ...props
141
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
142
+ return (
143
+ <SelectPrimitive.ScrollUpButton
144
+ data-slot="select-scroll-up-button"
145
+ className={cn(
146
+ "flex cursor-default items-center justify-center py-1",
147
+ className
148
+ )}
149
+ {...props}
150
+ >
151
+ <ChevronUpIcon className="size-4" />
152
+ </SelectPrimitive.ScrollUpButton>
153
+ )
154
+ }
155
+
156
+ function SelectScrollDownButton({
157
+ className,
158
+ ...props
159
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
160
+ return (
161
+ <SelectPrimitive.ScrollDownButton
162
+ data-slot="select-scroll-down-button"
163
+ className={cn(
164
+ "flex cursor-default items-center justify-center py-1",
165
+ className
166
+ )}
167
+ {...props}
168
+ >
169
+ <ChevronDownIcon className="size-4" />
170
+ </SelectPrimitive.ScrollDownButton>
171
+ )
172
+ }
173
+
174
+ export {
175
+ Select,
176
+ SelectContent,
177
+ SelectGroup,
178
+ SelectItem,
179
+ SelectLabel,
180
+ SelectScrollDownButton,
181
+ SelectScrollUpButton,
182
+ SelectSeparator,
183
+ SelectTrigger,
184
+ SelectValue,
185
+ }
src/components/ui/slider.tsx ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as SliderPrimitive from "@radix-ui/react-slider"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ function Slider({
9
+ className,
10
+ defaultValue,
11
+ value,
12
+ min = 0,
13
+ max = 100,
14
+ ...props
15
+ }: React.ComponentProps<typeof SliderPrimitive.Root>) {
16
+ const _values = React.useMemo(
17
+ () =>
18
+ Array.isArray(value)
19
+ ? value
20
+ : Array.isArray(defaultValue)
21
+ ? defaultValue
22
+ : [min, max],
23
+ [value, defaultValue, min, max]
24
+ )
25
+
26
+ return (
27
+ <SliderPrimitive.Root
28
+ data-slot="slider"
29
+ defaultValue={defaultValue}
30
+ value={value}
31
+ min={min}
32
+ max={max}
33
+ className={cn(
34
+ "relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",
35
+ className
36
+ )}
37
+ {...props}
38
+ >
39
+ <SliderPrimitive.Track
40
+ data-slot="slider-track"
41
+ className={cn(
42
+ "bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"
43
+ )}
44
+ >
45
+ <SliderPrimitive.Range
46
+ data-slot="slider-range"
47
+ className={cn(
48
+ "bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full"
49
+ )}
50
+ />
51
+ </SliderPrimitive.Track>
52
+ {Array.from({ length: _values.length }, (_, index) => (
53
+ <SliderPrimitive.Thumb
54
+ data-slot="slider-thumb"
55
+ key={index}
56
+ className="border-primary bg-background ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"
57
+ />
58
+ ))}
59
+ </SliderPrimitive.Root>
60
+ )
61
+ }
62
+
63
+ export { Slider }
src/components/ui/textarea.tsx ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
11
+ className
12
+ )}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ export { Textarea }
src/lib/exportUtils.ts ADDED
@@ -0,0 +1,463 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Document, Packer, Paragraph, TextRun, HeadingLevel, AlignmentType, Table, TableRow, TableCell, WidthType } from 'docx';
2
+ import { GeneratedQuestion } from '@/types/quiz';
3
+
4
+ export async function exportQuestionsToDocx(
5
+ questions: GeneratedQuestion[],
6
+ filename: string = 'quiz-questions.docx',
7
+ includeAnswers: boolean = true
8
+ ) {
9
+ // Create document
10
+ const doc = new Document({
11
+ sections: [{
12
+ properties: {},
13
+ children: [
14
+ // Title
15
+ new Paragraph({
16
+ text: 'Quiz Questions',
17
+ heading: HeadingLevel.HEADING_1,
18
+ alignment: AlignmentType.CENTER,
19
+ spacing: {
20
+ after: 400,
21
+ before: 400
22
+ }
23
+ }),
24
+
25
+ // Summary
26
+ new Paragraph({
27
+ children: [
28
+ new TextRun({
29
+ text: `Total Questions: ${questions.length}`,
30
+ size: 18,
31
+ color: '666666'
32
+ })
33
+ ],
34
+ alignment: AlignmentType.CENTER,
35
+ spacing: {
36
+ after: 300
37
+ }
38
+ }),
39
+
40
+ // Questions
41
+ ...questions.map((question, index) =>
42
+ renderQuestion(question, index + 1, includeAnswers)
43
+ ).flat()
44
+ ]
45
+ }]
46
+ });
47
+
48
+ // Generate and download the document
49
+ const blob = await Packer.toBlob(doc);
50
+ const url = window.URL.createObjectURL(blob);
51
+ const link = document.createElement('a');
52
+ link.href = url;
53
+ link.download = filename;
54
+ document.body.appendChild(link);
55
+ link.click();
56
+ document.body.removeChild(link);
57
+ window.URL.revokeObjectURL(url);
58
+ }
59
+
60
+ function renderQuestion(question: GeneratedQuestion, questionNumber: number, includeAnswers: boolean = true): any[] {
61
+ const elements: any[] = [];
62
+
63
+ // Question number and type
64
+ elements.push(
65
+ new Paragraph({
66
+ children: [
67
+ new TextRun({
68
+ text: `Question ${questionNumber}`,
69
+ bold: true,
70
+ size: 24
71
+ }),
72
+ new TextRun({
73
+ text: ` (${question.type})`,
74
+ size: 20,
75
+ color: '666666'
76
+ })
77
+ ],
78
+ spacing: {
79
+ after: 200,
80
+ before: 300
81
+ }
82
+ })
83
+ );
84
+
85
+ // Question stem
86
+ elements.push(
87
+ new Paragraph({
88
+ children: [
89
+ new TextRun({
90
+ text: question.stem,
91
+ size: 22
92
+ })
93
+ ],
94
+ spacing: {
95
+ after: 200
96
+ }
97
+ })
98
+ );
99
+
100
+ // Question content (handle different question types)
101
+ const contentElements = renderQuestionContent(question, includeAnswers);
102
+ elements.push(...contentElements);
103
+
104
+ // Points
105
+ elements.push(
106
+ new Paragraph({
107
+ children: [
108
+ new TextRun({
109
+ text: `Points: ${question.points}`,
110
+ bold: true,
111
+ size: 18,
112
+ color: '0066CC'
113
+ })
114
+ ],
115
+ spacing: {
116
+ after: 300
117
+ }
118
+ })
119
+ );
120
+
121
+ // Separator line
122
+ elements.push(
123
+ new Paragraph({
124
+ children: [
125
+ new TextRun({
126
+ text: '─'.repeat(50),
127
+ color: 'CCCCCC'
128
+ })
129
+ ],
130
+ alignment: AlignmentType.CENTER,
131
+ spacing: {
132
+ after: 200
133
+ }
134
+ })
135
+ );
136
+
137
+ return elements;
138
+ }
139
+
140
+ function renderQuestionContent(question: GeneratedQuestion, includeAnswers: boolean = true): any[] {
141
+ const elements: any[] = [];
142
+
143
+
144
+
145
+ if (question.content && typeof question.content === 'object') {
146
+ // Handle multiple choice questions
147
+ if (question.content.options && Array.isArray(question.content.options)) {
148
+ question.content.options.forEach((option: any, index: number) => {
149
+ const optionText = option.text || option.label || option;
150
+ const isCorrect = question.content.correctAnswer === index ||
151
+ question.content.correctAnswer === optionText ||
152
+ (question.content.correctAnswers && question.content.correctAnswers.includes(index));
153
+
154
+ elements.push(
155
+ new Paragraph({
156
+ children: [
157
+ new TextRun({
158
+ text: `${String.fromCharCode(65 + index)}. ${optionText}`,
159
+ size: 20,
160
+ color: includeAnswers && isCorrect ? '008000' : '000000',
161
+ bold: includeAnswers && isCorrect
162
+ })
163
+ ],
164
+ spacing: {
165
+ after: 100
166
+ }
167
+ })
168
+ );
169
+ });
170
+ }
171
+
172
+ // Handle multiple choice with answer field
173
+ if (question.content.answer && question.content.options && Array.isArray(question.content.options)) {
174
+ question.content.options.forEach((option: any, index: number) => {
175
+ const optionText = option.text || option.label || option;
176
+ const isCorrect = question.content.answer === index ||
177
+ question.content.answer === optionText ||
178
+ question.content.answer === option;
179
+
180
+ elements.push(
181
+ new Paragraph({
182
+ children: [
183
+ new TextRun({
184
+ text: `${String.fromCharCode(65 + index)}. ${optionText}`,
185
+ size: 20,
186
+ color: includeAnswers && isCorrect ? '008000' : '000000',
187
+ bold: includeAnswers && isCorrect
188
+ })
189
+ ],
190
+ spacing: {
191
+ after: 100
192
+ }
193
+ })
194
+ );
195
+ });
196
+ }
197
+
198
+ // Handle alternative multiple choice structures
199
+ if (question.content.choices && Array.isArray(question.content.choices)) {
200
+ question.content.choices.forEach((choice: any, index: number) => {
201
+ const choiceText = choice.text || choice.label || choice;
202
+ const isCorrect = question.content.correctAnswer === index ||
203
+ question.content.correctAnswer === choiceText ||
204
+ (question.content.correctAnswers && question.content.correctAnswers.includes(index));
205
+
206
+ elements.push(
207
+ new Paragraph({
208
+ children: [
209
+ new TextRun({
210
+ text: `${String.fromCharCode(65 + index)}. ${choiceText}`,
211
+ size: 20,
212
+ color: includeAnswers && isCorrect ? '008000' : '000000',
213
+ bold: includeAnswers && isCorrect
214
+ })
215
+ ],
216
+ spacing: {
217
+ after: 100
218
+ }
219
+ })
220
+ );
221
+ });
222
+ }
223
+
224
+ // Handle array-based options (direct array of strings)
225
+ if (Array.isArray(question.content) && question.content.length > 0 && typeof question.content[0] === 'string') {
226
+ question.content.forEach((option: string, index: number) => {
227
+ const isCorrect = question.content.correctAnswer === index ||
228
+ question.content.correctAnswer === option ||
229
+ (question.content.correctAnswers && question.content.correctAnswers.includes(index));
230
+
231
+ elements.push(
232
+ new Paragraph({
233
+ children: [
234
+ new TextRun({
235
+ text: `${String.fromCharCode(65 + index)}. ${option}`,
236
+ size: 20,
237
+ color: includeAnswers && isCorrect ? '008000' : '000000',
238
+ bold: includeAnswers && isCorrect
239
+ })
240
+ ],
241
+ spacing: {
242
+ after: 100
243
+ }
244
+ })
245
+ );
246
+ });
247
+ }
248
+
249
+ // Handle questions where content itself is the options array
250
+ if (Array.isArray(question.content) && question.content.length > 0) {
251
+ // Check if this looks like multiple choice options
252
+ const firstItem = question.content[0];
253
+ if (typeof firstItem === 'string' || (typeof firstItem === 'object' && (firstItem.text || firstItem.label))) {
254
+ question.content.forEach((option: any, index: number) => {
255
+ const optionText = typeof option === 'string' ? option : (option.text || option.label || option);
256
+ const isCorrect = question.content.correctAnswer === index ||
257
+ question.content.correctAnswer === optionText ||
258
+ (question.content.correctAnswers && question.content.correctAnswers.includes(index));
259
+
260
+ elements.push(
261
+ new Paragraph({
262
+ children: [
263
+ new TextRun({
264
+ text: `${String.fromCharCode(65 + index)}. ${optionText}`,
265
+ size: 20,
266
+ color: includeAnswers && isCorrect ? '008000' : '000000',
267
+ bold: includeAnswers && isCorrect
268
+ })
269
+ ],
270
+ spacing: {
271
+ after: 100
272
+ }
273
+ })
274
+ );
275
+ });
276
+ }
277
+ }
278
+
279
+ // Handle true/false questions
280
+ if (question.content.correctAnswer !== undefined && includeAnswers) {
281
+ const answer = question.content.correctAnswer === true ? 'True' : 'False';
282
+ elements.push(
283
+ new Paragraph({
284
+ children: [
285
+ new TextRun({
286
+ text: `Answer: ${answer}`,
287
+ bold: true,
288
+ size: 20,
289
+ color: '008000'
290
+ })
291
+ ],
292
+ spacing: {
293
+ after: 200
294
+ }
295
+ })
296
+ );
297
+ }
298
+
299
+ // Handle fill-in-the-blank questions
300
+ if (question.content.blanks && Array.isArray(question.content.blanks)) {
301
+ question.content.blanks.forEach((blank: any, index: number) => {
302
+ elements.push(
303
+ new Paragraph({
304
+ children: [
305
+ new TextRun({
306
+ text: `Blank ${index + 1}: `,
307
+ bold: true,
308
+ size: 20
309
+ }),
310
+ new TextRun({
311
+ text: includeAnswers ? (blank.answer || blank.correctAnswer || '_________') : '_________',
312
+ size: 20,
313
+ color: includeAnswers ? '008000' : '000000'
314
+ })
315
+ ],
316
+ spacing: {
317
+ after: 100
318
+ }
319
+ })
320
+ );
321
+ });
322
+ }
323
+
324
+ // Handle cloze questions (text with blanks)
325
+ if (question.content.text && question.content.blanks) {
326
+ let clozeText = question.content.text;
327
+ question.content.blanks.forEach((blank: any, index: number) => {
328
+ const placeholder = `___${index + 1}___`;
329
+ clozeText = clozeText.replace(placeholder, includeAnswers ? `[${blank.answer || blank.correctAnswer || '_________'}]` : '_________');
330
+ });
331
+
332
+ elements.push(
333
+ new Paragraph({
334
+ children: [
335
+ new TextRun({
336
+ text: clozeText,
337
+ size: 20
338
+ })
339
+ ],
340
+ spacing: {
341
+ after: 200
342
+ }
343
+ })
344
+ );
345
+ }
346
+
347
+ // Handle short answer questions
348
+ if ((question.content.expectedAnswer || question.content.sampleAnswer) && includeAnswers) {
349
+ const answer = question.content.expectedAnswer || question.content.sampleAnswer;
350
+ elements.push(
351
+ new Paragraph({
352
+ children: [
353
+ new TextRun({
354
+ text: 'Expected Answer: ',
355
+ bold: true,
356
+ size: 20
357
+ }),
358
+ new TextRun({
359
+ text: answer,
360
+ size: 20,
361
+ color: '008000'
362
+ })
363
+ ],
364
+ spacing: {
365
+ after: 200
366
+ }
367
+ })
368
+ );
369
+ }
370
+
371
+ // Handle matching questions
372
+ if (question.content.pairs && Array.isArray(question.content.pairs)) {
373
+ const table = new Table({
374
+ width: {
375
+ size: 100,
376
+ type: WidthType.PERCENTAGE,
377
+ },
378
+ rows: [
379
+ new TableRow({
380
+ children: [
381
+ new TableCell({
382
+ children: [new Paragraph({ text: 'Left Column', heading: HeadingLevel.HEADING_3 })],
383
+ width: { size: 50, type: WidthType.PERCENTAGE }
384
+ }),
385
+ new TableCell({
386
+ children: [new Paragraph({ text: 'Right Column', heading: HeadingLevel.HEADING_3 })],
387
+ width: { size: 50, type: WidthType.PERCENTAGE }
388
+ })
389
+ ]
390
+ }),
391
+ ...question.content.pairs.map((pair: any) =>
392
+ new TableRow({
393
+ children: [
394
+ new TableCell({
395
+ children: [new Paragraph({ text: pair.left || pair.item1 || '' })],
396
+ width: { size: 50, type: WidthType.PERCENTAGE }
397
+ }),
398
+ new TableCell({
399
+ children: [new Paragraph({ text: pair.right || pair.item2 || '' })],
400
+ width: { size: 50, type: WidthType.PERCENTAGE }
401
+ })
402
+ ]
403
+ })
404
+ )
405
+ ]
406
+ });
407
+
408
+ // Add the table to elements
409
+ elements.push(table);
410
+
411
+ // Add spacing after table
412
+ elements.push(
413
+ new Paragraph({
414
+ children: [],
415
+ spacing: { after: 200 }
416
+ })
417
+ );
418
+ }
419
+
420
+ // Fallback: Display any remaining content that wasn't handled by specific patterns
421
+ if (elements.length === 0 && question.content) {
422
+
423
+ if (typeof question.content === 'string') {
424
+ elements.push(
425
+ new Paragraph({
426
+ children: [
427
+ new TextRun({
428
+ text: question.content,
429
+ size: 20
430
+ })
431
+ ],
432
+ spacing: {
433
+ after: 200
434
+ }
435
+ })
436
+ );
437
+ } else if (typeof question.content === 'object') {
438
+ // Try to display object content as JSON-like format
439
+ Object.entries(question.content).forEach(([key, value]) => {
440
+ if (key !== 'options' && key !== 'choices' && key !== 'correctAnswer' && key !== 'correctAnswers') {
441
+ const displayValue = typeof value === 'string' ? value : JSON.stringify(value);
442
+ elements.push(
443
+ new Paragraph({
444
+ children: [
445
+ new TextRun({
446
+ text: `${key}: ${displayValue}`,
447
+ size: 18,
448
+ color: '666666'
449
+ })
450
+ ],
451
+ spacing: {
452
+ after: 100
453
+ }
454
+ })
455
+ );
456
+ }
457
+ });
458
+ }
459
+ }
460
+ }
461
+
462
+ return elements;
463
+ }
src/lib/utils.ts ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import { clsx, type ClassValue } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }