Tailwind 4 geçişi
This commit is contained in:
parent
48e7d34026
commit
a56bdc3e79
227 changed files with 3511 additions and 11204 deletions
43
README.md
43
README.md
|
|
@ -128,18 +128,18 @@ DevExtreme bileşenleri bu metadata'ya göre kendini kurar.
|
|||
|
||||
| Bileşen | Sürüm / Notlar |
|
||||
| --- | --- |
|
||||
| React | 19.2 |
|
||||
| Build | Vite 8 + TypeScript 5.9 |
|
||||
| UI kütüphaneleri | DevExtreme 26.1 (React), Tailwind CSS 3.4, kendi `components/ui` tasarım sistemi |
|
||||
| React | 19.3 |
|
||||
| Build | Vite 8 + TypeScript 7.0 (native `tsc`), lint: oxlint |
|
||||
| UI kütüphaneleri | DevExtreme 26.1 (React), Tailwind CSS 4.3 (`@tailwindcss/vite`, CSS-first yapılandırma), kendi `components/ui` tasarım sistemi |
|
||||
| Routing | react-router-dom 7 (dinamik route üretimi) |
|
||||
| State | easy-peasy (global store) + @tanstack/react-query |
|
||||
| State | easy-peasy (global store) |
|
||||
| Form | Formik + Yup, DevExtreme Form |
|
||||
| Kod editörü | Monaco Editor |
|
||||
| Runtime derleme | @babel/standalone (Custom Component) |
|
||||
| Runtime derleme | @babel/standalone 8 (Custom Component; JSX `classic` runtime) |
|
||||
| Takvim/Gantt | DevExtreme Scheduler/Gantt |
|
||||
| Gerçek zamanlı | @microsoft/signalr |
|
||||
| PWA | vite-plugin-pwa (Workbox) |
|
||||
| Node | 24.13 / npm 11 (`volta` ile sabitlenmiş) |
|
||||
| PWA | vite-plugin-pwa 2 (Workbox 7) |
|
||||
| Node | 24.22 / npm 12 (`volta` ile sabitlenmiş; kurulum betikleri `allowScripts` ile yönetilir) |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1140,12 +1140,25 @@ kaynak seed dosyalarıdır (`configs/seeds/*/data/App.DeveloperKit.CustomCompone
|
|||
depo kökünde, `ui/` dışındadır — derleme bağlamı yalnızca `ui/` klasörü olduğunda (docker, ayrı
|
||||
checkout) glob boş döner ve seed'e özgü sınıflar (`md:col-span-4`, `bg-gray-950/80`, `opacity-20`)
|
||||
CSS'e hiç girmez: uygulama yerelde doğru, sunucuda stilsiz görünür. Bu yüzden aynı sınıflar var
|
||||
olan `ui/safelist.txt` dosyasına da yazılır. Dosyayı zaten `twSafelistGenerator` eklentisi üretiyor
|
||||
(renk/ölçü listesi); eklenti artık seed dosyalarındaki `className` değerlerini de toplayıp
|
||||
`# --- custom component classes ---` işaretinin altına ekliyor. `safelist.txt` `ui/` içinde ve
|
||||
depoda olduğu için her ortamda taranır. Seed kökü görünmüyorsa işaretin altındaki liste olduğu gibi
|
||||
korunur — eksik bir bağlam listeyi silip sorunu büyütmez. Ayrı bir betik ya da ikinci bir safelist
|
||||
dosyası yoktur; liste her `npm run build` / `npm start` ile tazelenir.
|
||||
olan `ui/safelist.txt` dosyasına da yazılır. Dosyayı `ui/twSafelistGenerator.ts` Vite eklentisi
|
||||
üretir: seed dosyalarındaki `className` değerlerini toplar, derleme başında yazar ve geliştirmede seed
|
||||
klasörünü izler. `safelist.txt` `ui/` içinde ve depoda olduğu için her ortamda taranır
|
||||
(`src/assets/styles/tailwind/index.css` → `@source`). Seed kökü görünmüyorsa liste olduğu gibi
|
||||
korunur — eksik bir bağlam listeyi silip sorunu büyütmez. Çalışma anında veriden gelen renk/ölçü
|
||||
sınıfları (`bg-{renk}-{ton}`, `w-1/2` …) dosyaya değil aynı CSS'teki `@source inline(...)` satırlarına
|
||||
yazılır. Ayrı bir betik ya da ikinci bir safelist dosyası yoktur; liste her `npm run build` /
|
||||
`npm start` ile tazelenir.
|
||||
|
||||
**Tailwind 4 yapılandırması.** `tailwind.config.ts` ve PostCSS zinciri yoktur; tema (`gray` paleti,
|
||||
`sozsoft-*` renkleri, `1.2`–`1.4` aralıkları, font) `src/assets/styles/tailwind/index.css` içindeki
|
||||
`@theme` bloğundadır. Aynı dosya v3 davranışını koruyan uyumluluk kurallarını taşır: `dark` sınıf
|
||||
varyantı, dokunmatikte de çalışan `hover`, gri-200 kenarlık, gri-400 placeholder, butonda `pointer`
|
||||
imleci, varsayılan 3px mavi `ring`, veritabanındaki eski Custom Component kodu için `flex-shrink-*` /
|
||||
`flex-grow-*`. Kademelenme v3 ile aynıdır (`app.css`): yalnızca tema ve preflight katmandadır
|
||||
(en zayıf); `components/` + `template/` stilleri ve en sonda utility'ler katmansızdır. Bileşen
|
||||
stilleri katmana alınmaz — katmansız CSS her katmanı yendiği için stilini katmansız basan
|
||||
kütüphanelere (react-select, DevExtreme) yenilirdi. JS'te renk gerektiğinde değer kopyalanmaz,
|
||||
`themeColor()` (`src/utils/tailwind.ts`) temanın `var(--color-*)` değişkenini döndürür.
|
||||
|
||||
**Katalog düğümleri.** Kanvasın doğrudan çizdiği, derlenen bileşen listesinde yer almayan
|
||||
bileşenler tek bir sözlükte durur (`RUNTIME_NODE_COMPONENTS`): kanvas onu `VisualCanvas` içinde,
|
||||
|
|
@ -2104,8 +2117,8 @@ Ayrıntılı kurulum notları: [`configs/deployment/README.md`](configs/deployme
|
|||
cd ui
|
||||
npm start # geliştirme sunucusu
|
||||
npm run build # üretim derlemesi (metadata + version + vite build)
|
||||
npm run lint # ESLint
|
||||
npm run format # prettier --write + eslint --fix
|
||||
npm run lint # oxlint (.oxlintrc.json)
|
||||
npm run format # prettier --write + oxlint --fix
|
||||
```
|
||||
|
||||
### 21.3. Backend
|
||||
|
|
|
|||
|
|
@ -519,8 +519,11 @@ Bir çelişki varsa sıra: `ai.instructions.md` → `dotnet.instructions.md` →
|
|||
olmadığını kontrol et.
|
||||
- **Custom component sınıfları** → bileşen kodu veritabanında yaşar, Tailwind derlemede yalnızca
|
||||
seed dosyasını görür. Seed dosyası `ui/` dışında olduğu için aynı sınıflar `ui/safelist.txt`
|
||||
sonuna da yazılır (`twSafelistGenerator`, derlemede otomatik); yoksa uygulama sunucuda stilsiz
|
||||
kalır. İkinci bir safelist dosyası açma.
|
||||
dosyasına da yazılır (`ui/twSafelistGenerator.ts` Vite eklentisi, derlemede otomatik); yoksa
|
||||
uygulama sunucuda stilsiz kalır. İkinci bir safelist dosyası açma. Çalışma anında veriden üretilen
|
||||
sınıf (`bg-${renk}-500`) dosyaya değil `src/assets/styles/tailwind/index.css`'teki `@source inline`
|
||||
satırına eklenir. Sınıf adları Tailwind 4'tür (`shadow-xs`, `rounded-sm`, `bg-black/50`,
|
||||
`shrink-0`, `x!`); tema `tailwind.config.ts`'te değil aynı dosyanın `@theme` bloğundadır.
|
||||
- **Custom component kaydı/silinmesi** → `data/App.DeveloperKit.CustomComponents/{Id}.json`
|
||||
(Custom Components ekranının seed verisi); ekran klasör modundadır, her bileşen kendi satır
|
||||
dosyasındadır. Hem listeden hem Visual Designer'dan (`CustomComponentAppService`) yapılan kayıt
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -11,7 +11,7 @@
|
|||
"Description": null,
|
||||
"IsActive": true,
|
||||
"Dependencies": "",
|
||||
"Code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344/\",\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/crudendpoint/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600 dark:text-red-400\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 shadow-sm rounded-lg\">\n <thead className=\"bg-slate-100 dark:bg-slate-800\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 dark:border-slate-700 text-sm font-medium text-slate-700 dark:text-slate-200\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={item.id ?? rowIndex} className=\"hover:bg-slate-50 dark:hover:bg-slate-800\">\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800\">\n <Button\n type=\"button\"\n color=\"blue-500\"\n onClick={() => alert(item.name)}\n shape=\"round\"\n size=\"xs\"\n variant=\"solid\"\n id=\"c_mrix4c1a_qrybhk\"\n >\n Show Name\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;",
|
||||
"Code": "import React, { useEffect, useState } from \"react\";\nimport axios from \"axios\";\n\ninterface DynamicEntityComponentProps {\n title: string;\n}\n\nconst api = axios.create({\n baseURL: \"https://localhost:44344/\",\n});\n\nconst DynamicEntityComponent: React.FC<DynamicEntityComponentProps> = ({ title }) => {\n const [data, setData] = useState<Array<{ id: string; name: string }>>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const fetchData = async () => {\n setLoading(true);\n setError(null);\n\n try {\n const res = await api.get(`/api/app/crudendpoint/${title}`);\n const raw = Array.isArray(res.data) ? res.data : res.data?.items ?? [];\n\n const filtered = raw.map((item: any) => ({\n id: item.Id ?? item.id,\n name: item.Name ?? item.name,\n }));\n\n setData(filtered);\n } catch (err: any) {\n setError(err.message || \"Failed to fetch data\");\n } finally {\n setLoading(false);\n }\n };\n\n if (title) fetchData();\n }, [title]);\n\n if (loading) return <div>Loading...</div>;\n if (error) return <div className=\"text-red-600 dark:text-red-400\">Error: {error}</div>;\n if (!data.length) return <div>No records found</div>;\n\n const headers = [\"id\", \"name\", \"actions\"];\n\n return (\n <div className=\"overflow-auto\">\n <table className=\"min-w-full bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-700 shadow-xs rounded-lg\">\n <thead className=\"bg-slate-100 dark:bg-slate-800\">\n <tr>\n {headers.map((key) => (\n <th\n key={key}\n className=\"text-left px-4 py-2 border-b border-slate-200 dark:border-slate-700 text-sm font-medium text-slate-700 dark:text-slate-200\"\n >\n {key === \"actions\" ? \"Actions\" : key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {data.map((item, rowIndex) => (\n <tr key={item.id ?? rowIndex} className=\"hover:bg-slate-50 dark:hover:bg-slate-800\">\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.id}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800 text-sm text-slate-800 dark:text-slate-100\">\n {item.name}\n </td>\n <td className=\"px-4 py-2 border-b border-slate-100 dark:border-slate-800\">\n <Button\n type=\"button\"\n color=\"blue-500\"\n onClick={() => alert(item.name)}\n shape=\"round\"\n size=\"xs\"\n variant=\"solid\"\n id=\"c_mrix4c1a_qrybhk\"\n >\n Show Name\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n};\n\nexport default DynamicEntityComponent;",
|
||||
"Props": null,
|
||||
"DataSources": "",
|
||||
"LastModificationTime": null,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
44
ui/.oxlintrc.json
Normal file
44
ui/.oxlintrc.json
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
||||
"plugins": ["typescript", "react", "import", "oxc"],
|
||||
"categories": {
|
||||
"correctness": "error"
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2024": true
|
||||
},
|
||||
"settings": {
|
||||
"react": { "version": "19" }
|
||||
},
|
||||
"rules": {
|
||||
"react/rules-of-hooks": "error",
|
||||
"react/exhaustive-deps": "warn",
|
||||
"react/only-export-components": ["warn", { "allowConstantExport": true }],
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react/set-state-in-effect": "off",
|
||||
"react/refs": "off",
|
||||
"react/immutability": "off",
|
||||
"react/static-components": "off",
|
||||
"react/preserve-manual-memoization": "off",
|
||||
"react/purity": "off",
|
||||
"react/use-memo": "off",
|
||||
"react/no-did-update-set-state": "off",
|
||||
"no-eval": "off",
|
||||
"import/first": "warn",
|
||||
"import/newline-after-import": "warn",
|
||||
"import/no-duplicates": "error",
|
||||
"import/default": "off",
|
||||
"import/no-named-as-default": "off",
|
||||
"import/no-named-as-default-member": "off",
|
||||
"typescript/no-explicit-any": "off",
|
||||
"no-unused-vars": "off"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["vite.config.ts", "twSafelistGenerator.ts"],
|
||||
"env": { "browser": false, "node": true }
|
||||
}
|
||||
],
|
||||
"ignorePatterns": ["dist/**", "dev-dist/**", "public/**", "env.d.ts"]
|
||||
}
|
||||
2
ui/.vscode/extensions.json
vendored
2
ui/.vscode/extensions.json
vendored
|
|
@ -3,7 +3,7 @@
|
|||
"vscode.typescript-language-features",
|
||||
"esbenp.prettier-vscode",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"dbaemuer.vscode-eslint",
|
||||
"oxc.oxc-vscode",
|
||||
"vscode.npm"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
ARG ENV="dev"
|
||||
|
||||
FROM node:24-alpine
|
||||
FROM node:24.22-alpine
|
||||
ARG ENV=$ENV
|
||||
RUN apk add --no-cache ca-certificates && update-ca-certificates
|
||||
# Node/npm sürümü package.json `volta` alanıyla aynıdır.
|
||||
RUN apk add --no-cache ca-certificates && update-ca-certificates && \
|
||||
npm install -g npm@12.2.0
|
||||
|
||||
ENV GENERATE_SOURCEMAP=false
|
||||
ENV NODE_OPTIONS=--max-old-space-size=16384
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
import js from '@eslint/js'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
import tsPlugin from '@typescript-eslint/eslint-plugin'
|
||||
import importPlugin from 'eslint-plugin-import'
|
||||
import reactPlugin from 'eslint-plugin-react'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import prettier from 'eslint-config-prettier'
|
||||
import globals from 'globals'
|
||||
|
||||
export default [
|
||||
{
|
||||
ignores: [
|
||||
'node_modules/**',
|
||||
'dist/**',
|
||||
'dev-dist/**',
|
||||
'public/**',
|
||||
'env.d.ts',
|
||||
],
|
||||
},
|
||||
js.configs.recommended,
|
||||
{
|
||||
files: ['**/*.{js,jsx,ts,tsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
sourceType: 'module',
|
||||
globals: globals.browser,
|
||||
parserOptions: { ecmaFeatures: { jsx: true } },
|
||||
},
|
||||
plugins: {
|
||||
import: importPlugin,
|
||||
react: reactPlugin,
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
},
|
||||
settings: {
|
||||
react: { version: 'detect' },
|
||||
'import/parsers': { '@typescript-eslint/parser': ['.ts', '.tsx'] },
|
||||
'import/resolver': {
|
||||
typescript: { project: './tsconfig.eslint.json', alwaysTryTypes: true },
|
||||
},
|
||||
// Vite'in sanal modulleri diskte yoktur; cozucu onlari bulamaz, tipleri
|
||||
// `vite-env.d.ts` uzerinden gelir.
|
||||
'import/core-modules': ['virtual:pwa-register'],
|
||||
},
|
||||
rules: {
|
||||
...reactPlugin.configs.recommended.rules,
|
||||
...reactPlugin.configs['jsx-runtime'].rules,
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/exhaustive-deps': 'warn',
|
||||
...importPlugin.configs.recommended.rules,
|
||||
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
'import/first': 'warn',
|
||||
'import/default': 'off',
|
||||
'import/newline-after-import': 'warn',
|
||||
'import/no-named-as-default-member': 'off',
|
||||
'import/no-duplicates': 'error',
|
||||
'import/no-named-as-default': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'react/jsx-sort-props': [
|
||||
'warn',
|
||||
{
|
||||
callbacksLast: true,
|
||||
shorthandFirst: true,
|
||||
ignoreCase: true,
|
||||
reservedFirst: true,
|
||||
noSortAlphabetically: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: { parser: tsParser },
|
||||
plugins: { '@typescript-eslint': tsPlugin },
|
||||
rules: {
|
||||
...tsPlugin.configs.recommended.rules,
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
// TypeScript zaten tanimsiz tanimlayicilari yakalar; ESLint'in kapsam
|
||||
// analizi ise `EventListener` / `NotificationOptions` gibi yalnizca tip
|
||||
// olarak var olan DOM global'lerini bilmedigi icin yanlis alarm veriyor.
|
||||
// typescript-eslint'in de onerdigi ayar.
|
||||
'no-undef': 'off',
|
||||
},
|
||||
},
|
||||
prettier,
|
||||
// Derleme araclari Node'da CommonJS olarak calisir: tarayici globalleri yerine Node
|
||||
// globalleri gecerlidir ve Tailwind eklentisi `require` ile yuklenir (tailwind.config.ts
|
||||
// Node tarafindan okunur, bundle'a girmez).
|
||||
{
|
||||
files: ['tailwind.config.ts', 'postcss.config.cjs', 'twSafelistGenerator/**/*.js'],
|
||||
languageOptions: {
|
||||
globals: globals.node,
|
||||
sourceType: 'commonjs',
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-require-imports': 'off',
|
||||
},
|
||||
},
|
||||
]
|
||||
6511
ui/package-lock.json
generated
6511
ui/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -3,8 +3,8 @@
|
|||
"private": true,
|
||||
"elstarVersion": "2.1.6",
|
||||
"engines": {
|
||||
"node": ">=24.19.0",
|
||||
"npm": ">=11.19.0"
|
||||
"node": ">=24.22.0",
|
||||
"npm": ">=12.2.0"
|
||||
},
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
|
@ -17,82 +17,67 @@
|
|||
"build:production": "vite build",
|
||||
"preview": "vite preview",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"lint": "oxlint",
|
||||
"lint:fix": "oxlint --fix",
|
||||
"prettier": "prettier --ignore-path .gitignore src --check",
|
||||
"prettier:fix": "npm run prettier -- --write",
|
||||
"format": "npm run prettier:fix && npm run lint:fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/standalone": "^7.29.8",
|
||||
"@babel/standalone": "^8.0.7",
|
||||
"@dnd-kit/core": "^6.3.1",
|
||||
"@dnd-kit/sortable": "^10.0.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@floating-ui/react": "^0.27.20",
|
||||
"@marsidev/react-turnstile": "^1.6.0",
|
||||
"@marsidev/react-turnstile": "^1.6.2",
|
||||
"@microsoft/signalr": "^10.0.11",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"axios": "^1.19.0",
|
||||
"axios": "^1.20.0",
|
||||
"classnames": "^2.5.1",
|
||||
"dayjs": "^1.11.21",
|
||||
"devexpress-reporting-react": "26.1.4",
|
||||
"devextreme": "26.1.4",
|
||||
"devextreme-exceljs-fork": "^4.4.13",
|
||||
"devextreme-react": "26.1.4",
|
||||
"dompurify": "3.4.13",
|
||||
"dayjs": "^1.11.23",
|
||||
"devexpress-reporting-react": "26.1.5",
|
||||
"devextreme": "26.1.5",
|
||||
"devextreme-exceljs-fork": "^4.5.0",
|
||||
"devextreme-react": "26.1.5",
|
||||
"dompurify": "3.4.17",
|
||||
"easy-peasy": "^6.1.1",
|
||||
"emoji-picker-react": "^4.19.1",
|
||||
"emoji-picker-react": "^5.0.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"formik": "^2.4.9",
|
||||
"framer-motion": "^13.1.0",
|
||||
"framer-motion": "^14.3.0",
|
||||
"jspdf": "^4.2.1",
|
||||
"react": "^19.2.8",
|
||||
"react": "^19.3.1",
|
||||
"react-advanced-cropper": "^0.20.1",
|
||||
"react-arborist": "^3.16.0",
|
||||
"react-dom": "^19.2.8",
|
||||
"react-dom": "^19.3.1",
|
||||
"react-icons": "^5.7.0",
|
||||
"react-modal": "^3.16.3",
|
||||
"react-router-dom": "^7.18.2",
|
||||
"react-router-dom": "^7.18.4",
|
||||
"react-select": "^5.10.2",
|
||||
"yup": "^1.7.1",
|
||||
"zxing-wasm": "^3.1.4"
|
||||
"zxing-wasm": "^3.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.5",
|
||||
"@tailwindcss/typography": "^0.5.20",
|
||||
"@tailwindcss/vite": "^4.3.3",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/node": "^24.10.1",
|
||||
"@types/react": "^19.2.18",
|
||||
"@types/react-dom": "^19.2.4",
|
||||
"@types/node": "^24.19.2",
|
||||
"@types/react": "^19.3.0",
|
||||
"@types/react-dom": "^19.3.0",
|
||||
"@types/react-modal": "^3.16.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.67.0",
|
||||
"@typescript-eslint/parser": "^8.67.0",
|
||||
"@vitejs/plugin-react": "^6.0.5",
|
||||
"autoprefixer": "^10.5.4",
|
||||
"cssnano": "^8.0.5",
|
||||
"eslint": "^9.39.5",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-import-resolver-typescript": "^4.4.5",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "^7.1.1",
|
||||
"eslint-plugin-react-refresh": "^0.5.4",
|
||||
"globals": "^17.11.0",
|
||||
"postcss": "^8.5.26",
|
||||
"prettier": "^3.9.6",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"typescript": "5.9",
|
||||
"vite": "^8.2.1",
|
||||
"vite-plugin-pwa": "^1.3.0"
|
||||
"@vitejs/plugin-react": "^6.1.2",
|
||||
"oxlint": "^1.88.0",
|
||||
"prettier": "^3.9.10",
|
||||
"tailwindcss": "^4.3.3",
|
||||
"typescript": "^7.0.2",
|
||||
"vite": "^8.3.4",
|
||||
"vite-plugin-pwa": "^2.0.0",
|
||||
"workbox-build": "^7.4.1",
|
||||
"workbox-window": "^7.4.1"
|
||||
},
|
||||
"overrides": {
|
||||
"dompurify": "3.4.13",
|
||||
"glob": "13.0.6",
|
||||
"brace-expansion@1": "1.1.18",
|
||||
"brace-expansion@2": "2.1.4",
|
||||
"brace-expansion@5": "5.0.9",
|
||||
"fast-uri": "3.1.5",
|
||||
"dompurify": "3.4.17",
|
||||
"postcss-selector-parser": "7.1.6",
|
||||
"workbox-build": {
|
||||
"source-map": "0.8.0"
|
||||
},
|
||||
|
|
@ -101,7 +86,12 @@
|
|||
}
|
||||
},
|
||||
"volta": {
|
||||
"node": "24.19.0",
|
||||
"npm": "11.19.0"
|
||||
"node": "24.22.0",
|
||||
"npm": "12.2.0"
|
||||
},
|
||||
"allowScripts": {
|
||||
"core-js": false,
|
||||
"unrs-resolver": false,
|
||||
"inferno": false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
'tailwindcss/nesting': {},
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
cssnano: {},
|
||||
},
|
||||
}
|
||||
4516
ui/safelist.txt
4516
ui/safelist.txt
File diff suppressed because it is too large
Load diff
|
|
@ -1,3 +1,8 @@
|
|||
/* v3 kademelenmesi: preflight ve tema katmanda (en zayif), bilesen stilleri ve utility'ler
|
||||
katmansiz. Katmansiz CSS her katmani yendigi icin bilesen stilleri katmana alinsaydi
|
||||
react-select/DevExtreme gibi stilini katmansiz basan kutuphanelere yenilirdi; utility'ler
|
||||
en sonda oldugu icin esit ozgullukte bilesen stilini ezer. */
|
||||
@import './tailwind/index.css';
|
||||
@import './components/index.css';
|
||||
@import './template/index.css';
|
||||
@import './tailwind/index.css';
|
||||
@import 'tailwindcss/utilities.css' source(none);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
@apply w-full px-3 rounded-lg border border-gray-300 dark:border-gray-600
|
||||
bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100
|
||||
placeholder-gray-400 dark:placeholder-gray-500
|
||||
focus:outline-none focus:ring-2 focus:border-transparent
|
||||
focus:outline-hidden focus:ring-2 focus:border-transparent
|
||||
transition-colors duration-150 text-sm;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.button {
|
||||
@apply font-semibold focus:outline-none whitespace-nowrap;
|
||||
@apply font-semibold focus:outline-hidden whitespace-nowrap;
|
||||
|
||||
&.radius-round {
|
||||
@apply rounded-md;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
}
|
||||
|
||||
.card-shadow {
|
||||
@apply shadow border-b border-gray-200 dark:border-gray-600 dark:border-none;
|
||||
@apply shadow-sm border-b border-gray-200 dark:border-gray-600 dark:border-none;
|
||||
}
|
||||
|
||||
.card-header-border {
|
||||
|
|
|
|||
|
|
@ -4,11 +4,11 @@
|
|||
border
|
||||
border-gray-300
|
||||
dark:border-gray-600
|
||||
rounded
|
||||
rounded-sm
|
||||
cursor-pointer
|
||||
inline-block
|
||||
align-middle
|
||||
flex-shrink-0
|
||||
shrink-0
|
||||
p-0
|
||||
appearance-none
|
||||
transition-colors
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
@apply inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-sm
|
||||
bg-indigo-100 dark:bg-indigo-900/40
|
||||
text-indigo-700 dark:text-indigo-300
|
||||
select-none outline-none
|
||||
select-none outline-hidden
|
||||
focus-visible:ring-2 focus-visible:ring-indigo-500;
|
||||
}
|
||||
|
||||
|
|
@ -40,6 +40,6 @@
|
|||
|
||||
/* Input */
|
||||
.chips-input {
|
||||
@apply flex-1 min-w-[80px] outline-none bg-transparent text-sm
|
||||
@apply flex-1 min-w-[80px] outline-hidden bg-transparent text-sm
|
||||
text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
.close-btn {
|
||||
@apply outline-none;
|
||||
@apply outline-hidden;
|
||||
}
|
||||
|
||||
.close-btn-default {
|
||||
@apply text-xl rounded p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300;
|
||||
@apply text-xl rounded-sm p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,9 @@
|
|||
}
|
||||
|
||||
/* Sizes */
|
||||
.color-picker-sm .color-picker-swatch { @apply w-6 h-6 rounded; }
|
||||
.color-picker-sm .color-picker-swatch { @apply w-6 h-6 rounded-sm; }
|
||||
.color-picker-lg .color-picker-swatch { @apply w-10 h-10 rounded-lg; }
|
||||
.color-picker-xs .color-picker-swatch { @apply w-5 h-5 rounded; }
|
||||
.color-picker-xs .color-picker-swatch { @apply w-5 h-5 rounded-sm; }
|
||||
|
||||
/* Native hidden input */
|
||||
.color-picker-native {
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
.color-picker-text-input {
|
||||
@apply w-full text-sm px-2 py-1 rounded-md border border-gray-300 dark:border-gray-600
|
||||
bg-gray-50 dark:bg-gray-700 text-gray-900 dark:text-gray-100
|
||||
focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent
|
||||
focus:outline-hidden focus:ring-2 focus:ring-indigo-500 focus:border-transparent
|
||||
font-mono;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
margin: 0 !important;
|
||||
}
|
||||
|
||||
@screen sm {
|
||||
@media (width >= theme(--breakpoint-sm)) {
|
||||
.dialog {
|
||||
@apply max-w-xl;
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
@screen md {
|
||||
@media (width >= theme(--breakpoint-md)) {
|
||||
.dialog {
|
||||
@apply max-w-2xl;
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
@screen lg {
|
||||
@media (width >= theme(--breakpoint-lg)) {
|
||||
.dialog {
|
||||
@apply max-w-4xl;
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
@screen xl {
|
||||
@media (width >= theme(--breakpoint-xl)) {
|
||||
.dialog {
|
||||
@apply max-w-6xl;
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
@apply p-6 rounded-lg shadow-xl my-4 relative bg-white dark:bg-gray-800 flex flex-col overflow-hidden;
|
||||
}
|
||||
|
||||
@screen sm {
|
||||
@media (width >= theme(--breakpoint-sm)) {
|
||||
.dialog-content {
|
||||
max-height: calc(100vh - 8rem);
|
||||
@apply my-16;
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
.dialog-header,
|
||||
.dialog-footer {
|
||||
@apply flex-shrink-0;
|
||||
@apply shrink-0;
|
||||
}
|
||||
|
||||
.dialog-body {
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
.dialog-overlay {
|
||||
transition: all 0.15s ease-in-out;
|
||||
@apply bg-opacity-60 inset-0 fixed z-30 bg-black dark:bg-opacity-80;
|
||||
@apply bg-black/60 dark:bg-black/80 inset-0 fixed z-30;
|
||||
}
|
||||
|
||||
.dialog-overlay-after-open {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
.drawer-overlay {
|
||||
transition: all 0.3s ease-in-out;
|
||||
@apply bg-black bg-opacity-80 inset-0 fixed z-30;
|
||||
@apply bg-black/80 inset-0 fixed z-30;
|
||||
}
|
||||
|
||||
.drawer-overlay-after-open {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
.dropdown-menu {
|
||||
min-width: 160px;
|
||||
@apply rounded-md shadow-lg bg-white dark:bg-gray-700 dark:shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none p-1.5 absolute z-30;
|
||||
@apply rounded-md shadow-lg bg-white dark:bg-gray-700 dark:shadow-2xl ring-1 ring-black/5 focus:outline-hidden p-1.5 absolute z-30;
|
||||
|
||||
&.top-start {
|
||||
@apply ltr:left-0 rtl:right-0 bottom-full origin-bottom;
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@
|
|||
}
|
||||
|
||||
.image-viewer-toolbar-actions button {
|
||||
@apply p-1.5 rounded text-white/70 hover:text-white hover:bg-white/10
|
||||
@apply p-1.5 rounded-sm text-white/70 hover:text-white hover:bg-white/10
|
||||
transition-colors duration-150;
|
||||
}
|
||||
|
||||
.image-viewer-close {
|
||||
@apply ml-2 !text-white/90 hover:!text-red-400;
|
||||
@apply ml-2 text-white/90! hover:!text-red-400;
|
||||
}
|
||||
|
||||
/* Stage */
|
||||
|
|
@ -69,7 +69,7 @@
|
|||
}
|
||||
|
||||
.image-viewer-thumb {
|
||||
@apply w-14 h-14 rounded overflow-hidden border-2 border-transparent
|
||||
@apply w-14 h-14 rounded-sm overflow-hidden border-2 border-transparent
|
||||
opacity-50 hover:opacity-80 transition-all duration-150 shrink-0 p-0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
rounded-md
|
||||
w-full
|
||||
py-2 px-3
|
||||
focus:outline-none
|
||||
focus:outline-hidden
|
||||
focus:ring-1
|
||||
focus-within:ring-1
|
||||
appearance-none
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
}
|
||||
|
||||
.knob {
|
||||
@apply select-none outline-none;
|
||||
@apply select-none outline-hidden;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,14 +26,14 @@
|
|||
}
|
||||
|
||||
&.menu-item-themed {
|
||||
@apply text-gray-100 text-opacity-80;
|
||||
@apply text-gray-100/80;
|
||||
|
||||
&.menu-item-hoverable {
|
||||
@apply hover:text-opacity-100 hover:bg-gray-900 hover:bg-opacity-10;
|
||||
@apply hover:text-gray-100 hover:bg-gray-900/10;
|
||||
}
|
||||
|
||||
&.menu-item-active {
|
||||
@apply text-gray-100 bg-gray-900 bg-opacity-30 hover:bg-opacity-30;
|
||||
@apply text-gray-100 bg-gray-900/30 hover:bg-gray-900/30;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
}
|
||||
|
||||
&.menu-collapse-item-themed {
|
||||
@apply text-gray-100 text-opacity-80 hover:text-opacity-100 hover:bg-gray-900 hover:bg-opacity-10;
|
||||
@apply text-gray-100/80 hover:text-gray-100 hover:bg-gray-900/10;
|
||||
}
|
||||
|
||||
&.menu-collapse-item-transparent {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
}
|
||||
|
||||
&.menu-title-themed {
|
||||
@apply text-gray-100 text-opacity-50;
|
||||
@apply text-gray-100/50;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
}
|
||||
|
||||
.pagination-pager {
|
||||
@apply cursor-pointer relative mx-1 rounded inline-flex items-center h-8 w-8 justify-center text-sm font-semibold select-none;
|
||||
@apply cursor-pointer relative mx-1 rounded-sm inline-flex items-center h-8 w-8 justify-center text-sm font-semibold select-none;
|
||||
}
|
||||
|
||||
.pagination-pager-inactive {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
cursor-pointer
|
||||
inline-block
|
||||
align-middle
|
||||
flex-shrink-0
|
||||
shrink-0
|
||||
p-0
|
||||
appearance-none
|
||||
transition-colors
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.rate {
|
||||
@apply inline-flex items-center select-none outline-none;
|
||||
@apply inline-flex items-center select-none outline-hidden;
|
||||
}
|
||||
|
||||
.rate-star {
|
||||
|
|
@ -7,5 +7,5 @@
|
|||
}
|
||||
|
||||
.rate-star:focus-visible {
|
||||
@apply outline-2 outline-offset-2 outline-indigo-500 rounded;
|
||||
@apply outline-2 outline-offset-2 outline-indigo-500 rounded-sm;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
.segment-item-default {
|
||||
@apply font-semibold
|
||||
focus:outline-none
|
||||
focus:outline-hidden
|
||||
cursor-pointer
|
||||
select-none
|
||||
rounded-md
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
}
|
||||
|
||||
.select__multi-value {
|
||||
@apply rounded text-sm;
|
||||
@apply rounded-sm text-sm;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
}
|
||||
|
||||
.select__multi-value {
|
||||
@apply rounded text-xs;
|
||||
@apply rounded-sm text-xs;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +79,7 @@
|
|||
|
||||
&.hide-single-value {
|
||||
.select__single-value {
|
||||
@apply !hidden;
|
||||
@apply hidden!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@
|
|||
}
|
||||
|
||||
.skeleton-block {
|
||||
@apply rounded h-2.5 w-full;
|
||||
@apply rounded-sm h-2.5 w-full;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
/* Handle */
|
||||
.slider-handle {
|
||||
@apply absolute rounded-full bg-white border-2 border-indigo-500
|
||||
shadow-md cursor-grab z-10 outline-none
|
||||
shadow-md cursor-grab z-10 outline-hidden
|
||||
focus:ring-2 focus:ring-offset-1 transition-shadow duration-100
|
||||
hover:shadow-lg;
|
||||
top: 50%;
|
||||
|
|
@ -74,18 +74,18 @@
|
|||
px-1.5 py-0.5 text-xs font-medium
|
||||
bg-gray-800 dark:bg-gray-200
|
||||
text-white dark:text-gray-900
|
||||
rounded whitespace-nowrap pointer-events-none z-20;
|
||||
rounded-sm whitespace-nowrap pointer-events-none z-20;
|
||||
}
|
||||
|
||||
.slider-tooltip::after {
|
||||
content: '';
|
||||
@apply absolute left-1/2 -translate-x-1/2 -bottom-1;
|
||||
border: 4px solid transparent;
|
||||
border-top-color: theme('colors.gray.800');
|
||||
border-top-color: var(--color-gray-800);
|
||||
}
|
||||
|
||||
.dark .slider-tooltip::after {
|
||||
border-top-color: theme('colors.gray.200');
|
||||
border-top-color: var(--color-gray-200);
|
||||
}
|
||||
|
||||
/* Marks */
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
}
|
||||
|
||||
.switcher-checked-loading {
|
||||
@apply !text-white;
|
||||
@apply text-white!;
|
||||
}
|
||||
|
||||
.switcher-uncheck-loading {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.time-input-field {
|
||||
@apply ring-0 w-6 text-center outline-none bg-transparent;
|
||||
@apply ring-0 w-6 text-center outline-hidden bg-transparent;
|
||||
}
|
||||
|
||||
.time-input-wrapper {
|
||||
|
|
|
|||
|
|
@ -35,5 +35,5 @@
|
|||
}
|
||||
|
||||
.timeline-connect {
|
||||
@apply h-full w-[2px] bg-gray-200 dark:bg-gray-600 flex-grow;
|
||||
@apply h-full w-[2px] bg-gray-200 dark:bg-gray-600 grow;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,103 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@layer theme, base;
|
||||
@import 'tailwindcss/theme.css' layer(theme);
|
||||
@import 'tailwindcss/preflight.css' layer(base);
|
||||
@plugin '@tailwindcss/typography';
|
||||
|
||||
@source '../../../../index.html';
|
||||
@source '../../..';
|
||||
/* Custom Component siniflari: seed dosyasi `ui/` disinda oldugu icin twSafelistGenerator derlemede
|
||||
buraya yazar (vite.config.ts). */
|
||||
@source '../../../../safelist.txt';
|
||||
|
||||
/* Calisma aninda veriden gelen siniflar (renk, olcu); kaynakta gecmedikleri icin derlemeye elle
|
||||
alinir. Renk listesi temanin paletidir (`--color-*`). */
|
||||
@source inline('{,hover:,dark:,dark:hover:}text-{inherit,current,transparent,black,white,{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-{50,{100..900..100},950},sozsoft-{main,secondary,active,x,y}}');
|
||||
@source inline('{,hover:,active:,dark:,dark:hover:,dark:active:}bg-{inherit,current,transparent,black,white,{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-{50,{100..900..100},950},sozsoft-{main,secondary,active,x,y}}');
|
||||
@source inline('{,hover:,focus:,focus-within:}ring-{inherit,current,transparent,black,white,{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-{50,{100..900..100},950},sozsoft-{main,secondary,active,x,y}}');
|
||||
@source inline('{,focus:,focus-within:}border-{inherit,current,transparent,black,white,{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-{50,{100..900..100},950},sozsoft-{main,secondary,active,x,y}}');
|
||||
/* Button iki tonlu koyu tema: renk adi calisma aninda gelir. */
|
||||
@source inline('dark:bg-{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-500/20');
|
||||
@source inline('dark:hover:bg-{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-500/30');
|
||||
@source inline('dark:active:bg-{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-500/40');
|
||||
@source inline('{h,w,ml,mr}-{0,px,0.5,1,1.2,1.3,1.4,1.5,2,2.5,3,3.5,4,5,6,7,8,9,10,11,12,14,16,20,24,28,32,36,40,44,48,52,56,60,64,72,80,96,auto}');
|
||||
@source inline('{h,w}-{1/2,1/3,2/3,1/4,2/4,3/4,1/5,2/5,3/5,4/5,1/6,2/6,3/6,4/6,5/6,full,screen,min,max,fit}');
|
||||
@source inline('h-{svh,lvh,dvh}');
|
||||
@source inline('w-{1/12,2/12,3/12,4/12,5/12,6/12,7/12,8/12,9/12,10/12,11/12,svw,lvw,dvw}');
|
||||
@source inline('{,hover:,focus:,active:,dark:,sm:,md:,lg:,xl:,2xl:}{container,block,inline-block,inline-flex,hidden,absolute,relative,fixed,sticky,grid,flex,flex-col,flex-row,flex-wrap,truncate,rounded,border,shadow,uppercase,lowercase,capitalize,backdrop-blur,transition,transform}');
|
||||
@source inline('{,sm:,md:,lg:,xl:,2xl:}prose{,-sm,-base,-lg,-xl,-2xl}');
|
||||
@source inline('{,dark:}prose-invert');
|
||||
@source inline('prose-{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}');
|
||||
|
||||
/* v4'te kaldirilan adlar: veritabanina daha once kurulmus Custom Component kodu bunlari tasiyabilir
|
||||
(migrate var olan kaydi ezmez). */
|
||||
@utility flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@utility flex-shrink {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
@utility flex-grow-0 {
|
||||
flex-grow: 0;
|
||||
}
|
||||
@utility flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
@source inline('{,sm:,md:,lg:,xl:,2xl:}{flex-shrink-0,flex-shrink,flex-grow-0,flex-grow}');
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
/* v3 davranisi: hover dokunmatik cihazlarda da calisir. */
|
||||
@custom-variant hover (&:hover);
|
||||
|
||||
@theme {
|
||||
--font-sans: 'Helvetica Neue', 'Segoe UI', helvetica, verdana, sans-serif;
|
||||
|
||||
--color-gray-50: #f8f8f8;
|
||||
--color-gray-100: #eeeeee;
|
||||
--color-gray-200: #d6d6d6;
|
||||
--color-gray-300: #b8b8b8;
|
||||
--color-gray-400: #929292;
|
||||
--color-gray-500: #747474;
|
||||
--color-gray-600: #575757;
|
||||
--color-gray-700: #3f3f3f;
|
||||
--color-gray-800: #303030;
|
||||
--color-gray-900: #252525;
|
||||
--color-gray-950: #1f1f1f;
|
||||
|
||||
--color-sozsoft-main: #ff99c8;
|
||||
--color-sozsoft-secondary: #fcf6bd;
|
||||
--color-sozsoft-active: #d0f4de;
|
||||
--color-sozsoft-x: #a9def9;
|
||||
--color-sozsoft-y: #e4c1f9;
|
||||
|
||||
--spacing-1_2: 0.35rem;
|
||||
--spacing-1_3: 0.4rem;
|
||||
--spacing-1_4: 0.45rem;
|
||||
|
||||
/* v3 varsayilani: renksiz `ring` 3px yari saydam mavi. */
|
||||
--default-ring-width: 3px;
|
||||
--default-ring-color: color-mix(in oklab, var(--color-blue-500) 50%, transparent);
|
||||
}
|
||||
|
||||
/* v4 onyuklemesinin v3'ten farklari: kenarlik rengi, placeholder rengi, buton imleci. */
|
||||
@layer base {
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentcolor);
|
||||
}
|
||||
|
||||
input::placeholder,
|
||||
textarea::placeholder {
|
||||
color: var(--color-gray-400);
|
||||
}
|
||||
|
||||
button:not(:disabled),
|
||||
[role='button']:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root,
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@
|
|||
}
|
||||
|
||||
.header-action-item-hoverable {
|
||||
@apply hover:bg-black
|
||||
hover:bg-opacity-5
|
||||
@apply hover:bg-black/5
|
||||
hover:text-gray-900
|
||||
dark:hover:bg-black
|
||||
dark:hover:bg-black/40
|
||||
dark:hover:text-gray-100
|
||||
dark:hover:bg-opacity-40
|
||||
transition-colors
|
||||
duration-300
|
||||
ease-in-out;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
}
|
||||
|
||||
.horizontal-menu-themed .menu-item.horizontal-menu-tab-active {
|
||||
@apply text-opacity-100;
|
||||
@apply text-gray-100;
|
||||
}
|
||||
|
||||
/* Açılır menü: genel Dropdown'a dokunmadan yalnızca üst menünün panelleri kapsanır. */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.side-nav {
|
||||
@apply flex-col flex-auto flex-shrink-0 z-20 transition-all ease-in-out duration-200 print:hidden;
|
||||
@apply flex-col flex-auto shrink-0 z-20 transition-all ease-in-out duration-200 print:hidden;
|
||||
}
|
||||
|
||||
.side-nav-expand {
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
}
|
||||
|
||||
.side-nav-content {
|
||||
height: calc(100vh - theme('spacing.24'));
|
||||
height: calc(100vh - --spacing(24));
|
||||
@apply overflow-y-auto;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
.stacked-side-nav {
|
||||
@apply flex flex-auto sticky top-0 h-screen flex-shrink-0 z-20 transition-all ease-in-out duration-200 overflow-y-hidden print:hidden;
|
||||
@apply flex flex-auto sticky top-0 h-screen shrink-0 z-20 transition-all ease-in-out duration-200 overflow-y-hidden print:hidden;
|
||||
}
|
||||
|
||||
.stacked-side-nav-content {
|
||||
height: calc(100vh - theme("spacing.16"));
|
||||
height: calc(100vh - --spacing(16));
|
||||
@apply overflow-y-auto;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export const Splitter: React.FC<SplitterProps> = ({
|
|||
ref={splitterRef}
|
||||
className={`
|
||||
${isHorizontal ? 'w-1 cursor-col-resize' : 'h-1 cursor-row-resize'}
|
||||
bg-gray-300 dark:bg-gray-700 hover:bg-blue-500 dark:hover:bg-blue-600 transition-colors duration-200 flex-shrink-0
|
||||
bg-gray-300 dark:bg-gray-700 hover:bg-blue-500 dark:hover:bg-blue-600 transition-colors duration-200 shrink-0
|
||||
${isDragging ? 'bg-blue-500 dark:bg-blue-600' : ''}
|
||||
`}
|
||||
onMouseDown={handleMouseDown}
|
||||
|
|
@ -120,7 +120,7 @@ export const Splitter: React.FC<SplitterProps> = ({
|
|||
ref={splitterRef}
|
||||
className={`
|
||||
${isHorizontal ? 'w-1 cursor-col-resize' : 'h-1 cursor-row-resize'}
|
||||
bg-gray-300 dark:bg-gray-700 hover:bg-blue-500 dark:hover:bg-blue-600 transition-colors duration-200 flex-shrink-0
|
||||
bg-gray-300 dark:bg-gray-700 hover:bg-blue-500 dark:hover:bg-blue-600 transition-colors duration-200 shrink-0
|
||||
${isDragging ? 'bg-blue-500 dark:bg-blue-600' : ''}
|
||||
`}
|
||||
onMouseDown={handleMouseDown}
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ const STYLE_GROUPS = {
|
|||
'truncate',
|
||||
'whitespace-normal',
|
||||
'whitespace-nowrap',
|
||||
'break-words',
|
||||
'wrap-break-word',
|
||||
'leading-none',
|
||||
'leading-tight',
|
||||
'leading-normal',
|
||||
|
|
@ -263,8 +263,8 @@ const STYLE_GROUPS = {
|
|||
'border-slate-700',
|
||||
'border-sky-500',
|
||||
'rounded-none',
|
||||
'rounded-xs',
|
||||
'rounded-sm',
|
||||
'rounded',
|
||||
'rounded-md',
|
||||
'rounded-lg',
|
||||
'rounded-xl',
|
||||
|
|
@ -275,8 +275,8 @@ const STYLE_GROUPS = {
|
|||
],
|
||||
Effects: [
|
||||
'shadow-none',
|
||||
'shadow-xs',
|
||||
'shadow-sm',
|
||||
'shadow',
|
||||
'shadow-md',
|
||||
'shadow-lg',
|
||||
'shadow-xl',
|
||||
|
|
@ -284,10 +284,10 @@ const STYLE_GROUPS = {
|
|||
'opacity-50',
|
||||
'opacity-75',
|
||||
'opacity-100',
|
||||
'blur-xs',
|
||||
'blur-sm',
|
||||
'blur',
|
||||
'backdrop-blur-xs',
|
||||
'backdrop-blur-sm',
|
||||
'backdrop-blur',
|
||||
'transition',
|
||||
'transition-all',
|
||||
'duration-150',
|
||||
|
|
@ -307,8 +307,8 @@ const STYLE_GROUPS = {
|
|||
'pointer-events-auto',
|
||||
'resize',
|
||||
'resize-none',
|
||||
'outline-none',
|
||||
'focus:outline-none',
|
||||
'outline-hidden',
|
||||
'focus:outline-hidden',
|
||||
'hover:opacity-80',
|
||||
'hover:bg-slate-100',
|
||||
'focus:ring-2',
|
||||
|
|
@ -382,7 +382,7 @@ const StyleModal = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className="fixed inset-0 z-[100] flex items-center justify-center bg-black/60 p-4"
|
||||
className="fixed inset-0 z-100 flex items-center justify-center bg-black/60 p-4"
|
||||
onMouseDown={onClose}
|
||||
>
|
||||
<div
|
||||
|
|
@ -447,7 +447,7 @@ const StyleModal = ({
|
|||
{translate('::App.StyleModal.EditValueManually', { property: propertyName })}
|
||||
</label>
|
||||
<textarea
|
||||
className={`w-full rounded-md border border-slate-300 bg-white p-3 font-mono text-xs text-slate-800 outline-none focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-white ${mode === 'css' ? 'min-h-48' : 'min-h-20'}`}
|
||||
className={`w-full rounded-md border border-slate-300 bg-white p-3 font-mono text-xs text-slate-800 outline-hidden focus:border-sky-500 dark:border-slate-700 dark:bg-slate-900 dark:text-white ${mode === 'css' ? 'min-h-48' : 'min-h-20'}`}
|
||||
placeholder={
|
||||
mode === 'css' ? '.my-class { color: red; }' : 'my-card selected-state md:wide-card'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1658,7 +1658,7 @@ export const CUSTOM_COMPONENTS: ComponentDefinition[] = [
|
|||
rowSpan: 1,
|
||||
colStart: 1,
|
||||
rowStart: 1,
|
||||
className: 'bg-blue-100 p-4 border rounded',
|
||||
className: 'bg-blue-100 p-4 border rounded-sm',
|
||||
},
|
||||
{
|
||||
id: 'grid-item-2',
|
||||
|
|
@ -1667,7 +1667,7 @@ export const CUSTOM_COMPONENTS: ComponentDefinition[] = [
|
|||
rowSpan: 1,
|
||||
colStart: 2,
|
||||
rowStart: 1,
|
||||
className: 'bg-green-100 p-4 border rounded',
|
||||
className: 'bg-green-100 p-4 border rounded-sm',
|
||||
},
|
||||
{
|
||||
id: 'grid-item-3',
|
||||
|
|
@ -1676,7 +1676,7 @@ export const CUSTOM_COMPONENTS: ComponentDefinition[] = [
|
|||
rowSpan: 1,
|
||||
colStart: 3,
|
||||
rowStart: 1,
|
||||
className: 'bg-yellow-100 p-4 border rounded',
|
||||
className: 'bg-yellow-100 p-4 border rounded-sm',
|
||||
},
|
||||
{
|
||||
id: 'grid-item-4',
|
||||
|
|
@ -1685,7 +1685,7 @@ export const CUSTOM_COMPONENTS: ComponentDefinition[] = [
|
|||
rowSpan: 1,
|
||||
colStart: 1,
|
||||
rowStart: 2,
|
||||
className: 'bg-purple-100 p-4 border rounded',
|
||||
className: 'bg-purple-100 p-4 border rounded-sm',
|
||||
},
|
||||
{
|
||||
id: 'grid-item-5',
|
||||
|
|
@ -1694,7 +1694,7 @@ export const CUSTOM_COMPONENTS: ComponentDefinition[] = [
|
|||
rowSpan: 1,
|
||||
colStart: 3,
|
||||
rowStart: 2,
|
||||
className: 'bg-red-100 p-4 border rounded',
|
||||
className: 'bg-red-100 p-4 border rounded-sm',
|
||||
},
|
||||
],
|
||||
category: 'properties',
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
declare module '@babel/standalone' {
|
||||
export function transform(code: string, options?: any): { code: string; map?: any };
|
||||
export function transformSync(code: string, options?: any): { code: string; map?: any };
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ export default function Widget({
|
|||
<div
|
||||
onClick={onClick}
|
||||
className={classNames(
|
||||
'bg-white dark:bg-gray-900 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 flex flex-col justify-between',
|
||||
'bg-white dark:bg-gray-900 rounded-lg shadow-xs border border-gray-200 dark:border-gray-700 p-4 flex flex-col justify-between',
|
||||
onClick && 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800',
|
||||
className
|
||||
)}
|
||||
|
|
@ -89,7 +89,7 @@ export default function Widget({
|
|||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
'w-12 h-12 bg-gradient-to-br rounded-xl flex items-center justify-center shadow-sm',
|
||||
'w-12 h-12 bg-linear-to-br rounded-xl flex items-center justify-center shadow-xs',
|
||||
colorMap[safeColor].bg,
|
||||
'dark:' + colorMap[safeColor].darkBg
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ const DevExtremeBoundary = ({ children }: DevExtremeBoundaryProps) => {
|
|||
|
||||
if (configuredCulture !== cultureName) {
|
||||
return (
|
||||
<div className="flex flex-auto flex-col h-[100vh]">
|
||||
<div className="flex flex-auto flex-col h-screen">
|
||||
<Loading loading />
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ export const FileUploadArea: React.FC<FileUploadAreaProps> = ({
|
|||
<div className="border border-gray-200 dark:border-gray-700 rounded-lg p-4 dark:bg-gray-900/40">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-3 min-w-0 flex-1">
|
||||
<FaFile className="w-8 h-8 text-blue-500 flex-shrink-0" />
|
||||
<FaFile className="w-8 h-8 text-blue-500 shrink-0" />
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="font-medium text-gray-800 dark:text-gray-100 truncate">
|
||||
{selectedFile.name}
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
return (
|
||||
<div className="flex flex-col w-full mt-4">
|
||||
{/* Navigation Tabs */}
|
||||
<div className="flex space-x-1 mb-4 bg-white dark:bg-gray-800 dark:border-gray-800 rounded-lg p-1 shadow-sm border border-gray-200 flex-shrink-0">
|
||||
<div className="flex space-x-1 mb-4 bg-white dark:bg-gray-800 dark:border-gray-800 rounded-lg p-1 shadow-xs border border-gray-200 shrink-0">
|
||||
{['import', 'preview', 'history'].map((tab) => (
|
||||
<Button
|
||||
key={tab}
|
||||
|
|
@ -360,7 +360,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Template Generator - 2/3 width on large screens, full width on mobile */}
|
||||
<div className="lg:col-span-2">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xs border border-gray-200 dark:border-gray-700">
|
||||
<div className="px-3 py-3 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between">
|
||||
<h3 className="text-xl font-semibold text-gray-800 dark:text-gray-100 flex items-center">
|
||||
<FaDownload className="w-4 h-4 mr-2" />
|
||||
|
|
@ -471,7 +471,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
|
||||
{/* File Upload - 1/3 width on large screens, full width on mobile */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-4 h-full">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xs border border-gray-200 dark:border-gray-700 p-4 h-full">
|
||||
<h2 className="text-xl font-semibold text-gray-800 dark:text-gray-100 mb-4 flex items-center">
|
||||
<FaUpload className="w-5 h-5 mr-2 text-green-500" />
|
||||
{translate('::App.ListFormImportManager.UploadData')}
|
||||
|
|
@ -509,7 +509,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-12">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xs border border-gray-200 dark:border-gray-700 p-12">
|
||||
<div className="text-center text-gray-500 dark:text-gray-400">
|
||||
<FaEye className="w-16 h-16 mx-auto mb-4 text-gray-300 dark:text-gray-600" />
|
||||
<div className="text-xl font-medium mb-2">
|
||||
|
|
@ -523,7 +523,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
)}
|
||||
|
||||
{activeTab === 'history' && (
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xs border border-gray-200 dark:border-gray-700">
|
||||
<div className="divide-y divide-gray-100 dark:divide-gray-800">
|
||||
{importHistory.map((session) => (
|
||||
<div
|
||||
|
|
@ -643,7 +643,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
: 'bg-green-50 text-green-700 border border-green-200 dark:bg-gray-800 dark:text-green-300 dark:border-gray-700'
|
||||
}`}
|
||||
>
|
||||
<span className="mt-0.5 flex-shrink-0">
|
||||
<span className="mt-0.5 shrink-0">
|
||||
{session.status === 'executed_with_errors' ||
|
||||
session.status === 'failed' ||
|
||||
session.status === 'execute_failed' ? (
|
||||
|
|
@ -660,7 +660,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
|
||||
{/* Execute Details Section */}
|
||||
{expandedSessions.has(session.id) && (
|
||||
<div className="mt-3 bg-gradient-to-r from-indigo-50 to-blue-50 dark:from-gray-800 dark:to-gray-800 border border-indigo-100 dark:border-gray-700 rounded-lg shadow-sm hover:shadow-md transition-shadow">
|
||||
<div className="mt-3 bg-linear-to-r from-indigo-50 to-blue-50 dark:from-gray-800 dark:to-gray-800 border border-indigo-100 dark:border-gray-700 rounded-lg shadow-xs hover:shadow-md transition-shadow">
|
||||
<div className="p-3">
|
||||
{loadingExecutes.has(session.id) ? (
|
||||
<div className="flex items-center space-x-2 text-gray-500 dark:text-gray-400 py-2">
|
||||
|
|
@ -676,7 +676,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
<div key={execute.id} className="p-3 rounded-lg dark:bg-gray-900/40">
|
||||
<div className="flex items-center justify-between">
|
||||
{/* Sol: Tarih */}
|
||||
<div className="flex-shrink-0">
|
||||
<div className="shrink-0">
|
||||
<div className="text-lg text-gray-500 dark:text-gray-400">
|
||||
{new Date(execute.creationTime).toLocaleString()}
|
||||
</div>
|
||||
|
|
@ -711,7 +711,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
</div>
|
||||
|
||||
{/* Sağ: Status */}
|
||||
<div className="flex items-center space-x-2 flex-shrink-0">
|
||||
<div className="flex items-center space-x-2 shrink-0">
|
||||
{getExecuteStatusIcon(execute.status)}
|
||||
<div
|
||||
className={`text-xs font-medium ${getExecuteStatusColor(execute.status)}`}
|
||||
|
|
@ -753,7 +753,7 @@ export const ImportDashboard: React.FC<ImportDashboardProps> = ({ gridDto }) =>
|
|||
</Button>
|
||||
|
||||
{expandedErrors.has(execute.id) && (
|
||||
<div className="mt-2 max-h-48 overflow-y-auto rounded border border-orange-200 bg-orange-50 dark:border-gray-700 dark:bg-gray-800">
|
||||
<div className="mt-2 max-h-48 overflow-y-auto rounded-sm border border-orange-200 bg-orange-50 dark:border-gray-700 dark:bg-gray-800">
|
||||
{parseErrors(execute.errorsJson).length > 0 ? (
|
||||
<table className="w-full text-xs">
|
||||
<thead className="bg-orange-100 dark:bg-gray-800 sticky top-0">
|
||||
|
|
|
|||
|
|
@ -147,12 +147,12 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xs border border-gray-200 dark:border-gray-700">
|
||||
{/* Header */}
|
||||
<div className="p-3 border-b border-gray-200 dark:border-gray-700">
|
||||
<div className="flex flex-col lg:flex-row lg:items-center lg:justify-center gap-4">
|
||||
{/* Başlık kısmı - Üstte mobile, solda desktop */}
|
||||
<div className="flex items-center order-1 lg:order-none">
|
||||
<div className="flex items-center order-1 lg:order-0">
|
||||
<FaEye className="w-5 h-5 mr-2 text-blue-500" />
|
||||
<h3 className="text-xl font-semibold text-gray-800 dark:text-gray-100">
|
||||
{translate('::App.ListFormImportManager.ImportPreviewTitle')}
|
||||
|
|
@ -160,7 +160,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
</div>
|
||||
|
||||
{/* İstatistik kartları - Mobile'da alt alta, desktop'ta yan yana */}
|
||||
<div className="order-3 lg:order-none lg:absolute lg:left-1/2 lg:transform lg:-translate-x-1/2">
|
||||
<div className="order-3 lg:order-0 lg:absolute lg:left-1/2 lg:transform lg:-translate-x-1/2">
|
||||
<div className="flex flex-col sm:flex-row justify-center gap-2">
|
||||
<div className="text-center px-3 py-1 bg-blue-50 dark:bg-gray-800 rounded-full border border-blue-200 dark:border-gray-700 font-bold text-blue-600 dark:text-blue-300">
|
||||
{previewData?.rows?.length || session.totalRows || 0}{' '}
|
||||
|
|
@ -172,7 +172,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
</div>
|
||||
|
||||
{/* Durum göstergesi - Altta mobile, sağda desktop */}
|
||||
<div className="flex justify-center lg:justify-end items-center order-2 lg:order-none lg:ml-auto w-full lg:w-auto">
|
||||
<div className="flex justify-center lg:justify-end items-center order-2 lg:order-0 lg:ml-auto w-full lg:w-auto">
|
||||
<span
|
||||
className={`px-3 py-1 rounded-full text-sm font-medium border w-full lg:w-auto text-center ${getStatusColor(
|
||||
session.status,
|
||||
|
|
@ -201,7 +201,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
type="checkbox"
|
||||
checked={selectAll}
|
||||
onChange={handleSelectAll}
|
||||
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
className="rounded-sm border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
</th>
|
||||
{previewData.headers.map((header: string, index: number) => (
|
||||
|
|
@ -228,7 +228,7 @@ export const ImportPreview: React.FC<ImportPreviewProps> = ({
|
|||
type="checkbox"
|
||||
checked={selectedRows.includes(rowIndex)}
|
||||
onChange={() => handleRowSelect(rowIndex)}
|
||||
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
className="rounded-sm border-gray-300 text-blue-600 focus:ring-blue-500"
|
||||
/>
|
||||
</td>
|
||||
{row.map((cell, cellIndex) => (
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export const ImportProgress: React.FC<ImportProgressProps> = ({ session }) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 p-6">
|
||||
<div className="bg-white dark:bg-gray-900 rounded-xl shadow-xs border border-gray-200 dark:border-gray-700 p-6">
|
||||
<div className="text-center space-y-6">
|
||||
{/* Status Icon */}
|
||||
<div className="flex justify-center">{getStatusIcon()}</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const AuthLayout = () => {
|
|||
const layoutType = useStoreState((state) => state.theme.layout.type)
|
||||
|
||||
return (
|
||||
<div className="app-layout-blank flex flex-auto flex-col h-[100vh]">
|
||||
<div className="app-layout-blank flex flex-auto flex-col h-screen">
|
||||
{layoutType === LAYOUT_TYPE_BLANK ? (
|
||||
<View />
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const ConfiguratorToggle = () => {
|
|||
|
||||
const BlankLayout = () => {
|
||||
return (
|
||||
<div className="app-layout-blank flex flex-auto flex-col h-[100vh]">
|
||||
<div className="app-layout-blank flex flex-auto flex-col h-screen">
|
||||
<View />
|
||||
<ConfiguratorToggle />
|
||||
<SidePanel className="hidden" />
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ const ClassicLayout = () => {
|
|||
<div className="flex flex-col flex-auto min-h-screen min-w-0 relative w-full">
|
||||
<Header
|
||||
container={false}
|
||||
className="shadow dark:shadow-2xl"
|
||||
className="shadow-sm dark:shadow-2xl"
|
||||
headerStart={<HeaderActionsStart />}
|
||||
headerEnd={<HeaderActionsEnd />}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const DeckedLayout = () => {
|
|||
<div className="flex flex-col flex-auto min-h-screen min-w-0 relative w-full">
|
||||
<Header
|
||||
container={false}
|
||||
className="shadow dark:shadow-2xl"
|
||||
className="shadow-sm dark:shadow-2xl"
|
||||
headerStart={<HeaderActionsStart />}
|
||||
headerEnd={<HeaderActionsEnd />}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class LayoutChunkErrorBoundary extends Component<{ children: ReactNode }, { fail
|
|||
</p>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded bg-indigo-600 px-4 py-2 text-sm font-medium text-white"
|
||||
className="rounded-sm bg-indigo-600 px-4 py-2 text-sm font-medium text-white"
|
||||
onClick={() => window.location.reload()}
|
||||
>
|
||||
Reload
|
||||
|
|
@ -145,7 +145,7 @@ const Layout = () => {
|
|||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex flex-auto flex-col h-[100vh]">
|
||||
<div className="flex flex-auto flex-col h-screen">
|
||||
<Loading loading />
|
||||
</div>
|
||||
)
|
||||
|
|
@ -158,7 +158,7 @@ const Layout = () => {
|
|||
<SkipToContent />
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="flex flex-auto flex-col h-[100vh]">
|
||||
<div className="flex flex-auto flex-col h-screen">
|
||||
<Loading loading />
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ const PublicLayout = () => {
|
|||
{isComponentRegistered(PUBLIC_HEADER_COMPONENT) &&
|
||||
renderComponent(PUBLIC_HEADER_COMPONENT)}
|
||||
|
||||
<main className="flex-grow" id="main-content">
|
||||
<main className="grow" id="main-content">
|
||||
<View />
|
||||
</main>
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ const SimpleLayout = () => {
|
|||
<div className="flex flex-col flex-auto min-h-screen min-w-0 relative w-full">
|
||||
<Header
|
||||
container={false}
|
||||
className="shadow dark:shadow-2xl"
|
||||
className="shadow-sm dark:shadow-2xl"
|
||||
headerStart={<HeaderActionsStart />}
|
||||
headerMiddle={<HorizontalNav />}
|
||||
headerEnd={<HeaderActionsEnd />}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ const StackedSideLayout = () => {
|
|||
<div className="flex flex-col flex-auto min-h-screen min-w-0 relative w-full">
|
||||
<Header
|
||||
container={false}
|
||||
className="shadow dark:shadow-2xl"
|
||||
className="shadow-sm dark:shadow-2xl"
|
||||
headerStart={<HeaderActionsStart />}
|
||||
headerEnd={<HeaderActionsEnd />}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export const Basket: React.FC<BasketProps> = ({
|
|||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 overflow-hidden">
|
||||
<div className="absolute inset-0 bg-black bg-opacity-50" onClick={onClose} />
|
||||
<div className="absolute inset-0 bg-black/50" onClick={onClose} />
|
||||
|
||||
<div className="absolute right-0 top-0 h-full w-full max-w-md bg-white shadow-xl dark:bg-gray-900">
|
||||
<div className="flex flex-col h-full">
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ export const BillingControls: React.FC<BillingControlsProps> = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`sticky z-20 bg-white border-b border-gray-200 shadow-sm mb-6 transition-all duration-300 dark:border-gray-800 dark:bg-gray-900 dark:shadow-gray-950/40 ${
|
||||
isScrolled ? 'top-[6rem]' : 'top-[6.5rem]'
|
||||
className={`sticky z-20 bg-white border-b border-gray-200 shadow-xs mb-6 transition-all duration-300 dark:border-gray-800 dark:bg-gray-900 dark:shadow-gray-950/40 ${
|
||||
isScrolled ? 'top-24' : 'top-26'
|
||||
}`}
|
||||
>
|
||||
<div className="p-2">
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({ onBack, onComplete, ba
|
|||
<form onSubmit={handleSubmit} className="flex flex-col lg:flex-row gap-6">
|
||||
{/* 3 Sütun: Ödeme Yöntemi | Taksit Seçenekleri | Sipariş Özeti */}
|
||||
<div className="w-full lg:w-1/3 flex flex-col gap-6">
|
||||
<div className="bg-white rounded-xl shadow border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<div className="bg-white rounded-xl shadow-sm border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<h2 className="text-lg font-semibold mb-4 flex items-center text-gray-900 dark:text-gray-100">
|
||||
<FaCalendarAlt className="w-5 h-5 text-green-600 mr-2" />
|
||||
Lisans Bilgileri
|
||||
|
|
@ -198,7 +198,7 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({ onBack, onComplete, ba
|
|||
|
||||
<div className="w-full lg:w-1/3 flex flex-col gap-6">
|
||||
{/* 1. Sütun: Ödeme Yöntemi */}
|
||||
<div className="bg-white rounded-xl shadow border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<div className="bg-white rounded-xl shadow-sm border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<h2 className="text-lg font-semibold mb-4 flex items-center">
|
||||
<FaLock className="w-5 h-5 text-green-600 mr-2" />{' '}
|
||||
{translate('::App.Listform.ListformField.PaymentMethodId')}
|
||||
|
|
@ -209,7 +209,7 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({ onBack, onComplete, ba
|
|||
key={method.id}
|
||||
className={`group flex items-center gap-3 rounded-xl border p-4 cursor-pointer transition-all ${
|
||||
selectedPaymentMethod === method.name
|
||||
? 'border-blue-500 bg-blue-50 shadow-sm ring-1 ring-blue-500/20 dark:border-blue-400 dark:bg-blue-950/30 dark:ring-blue-400/20'
|
||||
? 'border-blue-500 bg-blue-50 shadow-xs ring-1 ring-blue-500/20 dark:border-blue-400 dark:bg-blue-950/30 dark:ring-blue-400/20'
|
||||
: 'border-gray-200 bg-white hover:border-blue-300 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-950/40 dark:hover:border-blue-500 dark:hover:bg-gray-800/70'
|
||||
}`}
|
||||
>
|
||||
|
|
@ -257,7 +257,7 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({ onBack, onComplete, ba
|
|||
|
||||
{/* Taksit Seçenekleri */}
|
||||
{selectedPaymentMethod === defaultPaymentMethod && (
|
||||
<div className="bg-white rounded-xl shadow border p-4 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<div className="bg-white rounded-xl shadow-sm border p-4 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<h3 className="text-md font-medium text-gray-800 dark:text-gray-100 mb-2">
|
||||
{translate('::App.Orders.InstallmentOptions')}
|
||||
</h3>
|
||||
|
|
@ -309,7 +309,7 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({ onBack, onComplete, ba
|
|||
<div className="w-full lg:w-1/3 flex flex-col gap-6">
|
||||
{/* Kart Bilgileri */}
|
||||
{selectedPaymentMethod === defaultPaymentMethod && (
|
||||
<div className="bg-white rounded-xl shadow border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40 space-y-3">
|
||||
<div className="bg-white rounded-xl shadow-sm border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40 space-y-3">
|
||||
<h3 className="text-md font-medium text-gray-800 dark:text-gray-100 mb-3">
|
||||
{translate('::App.PaymentCard.CardTitle')}
|
||||
</h3>
|
||||
|
|
@ -358,7 +358,7 @@ export const PaymentForm: React.FC<PaymentFormProps> = ({ onBack, onComplete, ba
|
|||
)}
|
||||
|
||||
{/* Sipariş Özeti ve Butonlar */}
|
||||
<div className="bg-white rounded-xl shadow border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<div className="bg-white rounded-xl shadow-sm border p-6 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<h3 className="text-lg font-semibold text-gray-900 dark:text-gray-100 mb-4">
|
||||
{translate('::App.PaymentSummary.SummaryTitle')}
|
||||
</h3>
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export const ProductCard: React.FC<ProductCardProps> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden hover:shadow-lg transition-all duration-300 group flex flex-col h-full dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<div className="bg-white rounded-xl shadow-xs border border-gray-200 overflow-hidden hover:shadow-lg transition-all duration-300 group flex flex-col h-full dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
{product.imageUrl && (
|
||||
<div className="aspect-video overflow-hidden">
|
||||
<img
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ export const ProductCatalog: React.FC<ProductCatalogProps> = ({
|
|||
|
||||
return (
|
||||
<div className="flex flex-col lg:flex-row gap-8">
|
||||
<aside className="lg:w-64 flex-shrink-0">
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-2 sticky top-40 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<aside className="lg:w-64 shrink-0">
|
||||
<div className="bg-white rounded-lg shadow-xs border border-gray-200 p-2 sticky top-40 dark:border-gray-700 dark:bg-gray-900 dark:shadow-gray-950/40">
|
||||
<div className="flex items-center space-x-2 mb-4">
|
||||
<FaFilter className="w-5 h-5 text-gray-600 dark:text-gray-300" />
|
||||
<h3 className="font-semibold text-gray-900 dark:text-gray-100">
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<Button
|
||||
onClick={() => handleCustomerTypeChange(true)}
|
||||
variant="plain"
|
||||
className={`relative block h-auto w-full p-4 border-2 rounded-xl transition-all text-left select-none shadow-sm ${
|
||||
className={`relative block h-auto w-full p-4 border-2 rounded-xl transition-all text-left select-none shadow-xs ${
|
||||
isExisting === true
|
||||
? 'border-blue-600 bg-blue-100 shadow-lg ring-4 ring-blue-200 scale-[1.02] dark:border-sky-400 dark:bg-sky-950/60 dark:ring-sky-500/30'
|
||||
: 'border-gray-200 bg-white hover:border-blue-400 hover:bg-blue-50/60 dark:border-gray-700 dark:bg-gray-800/70 dark:hover:border-sky-500 dark:hover:bg-sky-950/30'
|
||||
|
|
@ -586,7 +586,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
<Button
|
||||
onClick={() => handleCustomerTypeChange(false)}
|
||||
variant="plain"
|
||||
className={`relative block h-auto w-full p-4 border-2 rounded-xl transition-all text-left select-none shadow-sm ${
|
||||
className={`relative block h-auto w-full p-4 border-2 rounded-xl transition-all text-left select-none shadow-xs ${
|
||||
isExisting === false
|
||||
? 'border-blue-600 bg-blue-100 shadow-lg ring-4 ring-blue-200 scale-[1.02] dark:border-sky-400 dark:bg-sky-950/60 dark:ring-sky-500/30'
|
||||
: 'border-gray-200 bg-white hover:border-blue-400 hover:bg-blue-50/60 dark:border-gray-700 dark:bg-gray-800/70 dark:hover:border-sky-500 dark:hover:bg-sky-950/30'
|
||||
|
|
@ -641,7 +641,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
|
|||
icon={<FaSearch className="w-4 h-4" />}
|
||||
variant="solid"
|
||||
size="sm"
|
||||
className="!h-[40px] min-w-[180px] sm:mr-2 sm:rounded-r-lg sm:rounded-l-none [&>span]:gap-2"
|
||||
className="h-[40px]! min-w-[180px] sm:mr-2 sm:rounded-r-lg sm:rounded-l-none [&>span]:gap-2"
|
||||
>
|
||||
{isLoadingTenant
|
||||
? translate('::App.Tenant.Searching')
|
||||
|
|
|
|||
|
|
@ -86,8 +86,8 @@ interface PublicThemeToggleProps {
|
|||
|
||||
export const PublicThemeToggle = ({
|
||||
className = 'inline-flex h-9 items-center rounded-lg p-0.5',
|
||||
buttonClassName = '!h-8 !w-8 xl:!w-auto !px-0 xl:!px-2.5 !border-transparent !shadow-none !bg-transparent !text-gray-300 hover:!bg-transparent hover:!text-white',
|
||||
activeClassName = '!bg-white !text-gray-950',
|
||||
buttonClassName = 'h-8! w-8! xl:w-auto! px-0! xl:px-2.5! border-transparent! shadow-none! bg-transparent! text-gray-300! hover:bg-transparent! hover:text-white!',
|
||||
activeClassName = 'bg-white! text-gray-950!',
|
||||
iconSize = 15,
|
||||
}: PublicThemeToggleProps) => {
|
||||
const [isDarkMode, setThemeMode] = useDarkMode()
|
||||
|
|
@ -99,14 +99,14 @@ export const PublicThemeToggle = ({
|
|||
active: !isDarkMode,
|
||||
title: '::App.Theme.LightMode',
|
||||
icon: <LuSun size={iconSize} strokeWidth={1.8} />,
|
||||
shape: '!rounded-l-md !rounded-r-none',
|
||||
shape: 'rounded-l-md! rounded-r-none!',
|
||||
},
|
||||
{
|
||||
mode: THEME_ENUM.MODE_DARK,
|
||||
active: isDarkMode,
|
||||
title: '::App.Theme.DarkMode',
|
||||
icon: <LuMoon size={iconSize} strokeWidth={1.8} />,
|
||||
shape: '!rounded-r-md !rounded-l-none',
|
||||
shape: 'rounded-r-md! rounded-l-none!',
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ export const PublicDemoButton = ({ className = '' }: { className?: string }) =>
|
|||
|
||||
return (
|
||||
<Button
|
||||
className={`group !h-9 !w-9 !overflow-visible !bg-transparent !px-0 !text-gray-200 !shadow-none transition-colors hover:!bg-transparent hover:!text-white ${className}`}
|
||||
className={`group h-9! w-9! overflow-visible! bg-transparent! px-0! text-gray-200! shadow-none! transition-colors hover:bg-transparent! hover:text-white! ${className}`}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="plain"
|
||||
|
|
@ -147,9 +147,9 @@ export const PublicDemoButton = ({ className = '' }: { className?: string }) =>
|
|||
closeMobileMenu?.()
|
||||
}}
|
||||
>
|
||||
<span className="relative inline-flex h-7 w-7 items-center justify-center overflow-visible rounded-full border-2 border-stone-700 bg-gradient-to-b from-red-400 via-red-600 to-red-800 shadow-[inset_0_-3px_6px_rgba(0,0,0,0.35),0_1px_3px_rgba(0,0,0,0.35)] ring-1 ring-black/60 transition-all duration-200 group-hover:scale-105 group-hover:from-red-300 group-hover:via-red-500 group-hover:to-red-700 group-hover:shadow-[inset_0_-3px_6px_rgba(0,0,0,0.3),0_2px_8px_rgba(239,68,68,0.35)]">
|
||||
<span className="relative inline-flex h-7 w-7 items-center justify-center overflow-visible rounded-full border-2 border-stone-700 bg-linear-to-b from-red-400 via-red-600 to-red-800 shadow-[inset_0_-3px_6px_rgba(0,0,0,0.35),0_1px_3px_rgba(0,0,0,0.35)] ring-1 ring-black/60 transition-all duration-200 group-hover:scale-105 group-hover:from-red-300 group-hover:via-red-500 group-hover:to-red-700 group-hover:shadow-[inset_0_-3px_6px_rgba(0,0,0,0.3),0_2px_8px_rgba(239,68,68,0.35)]">
|
||||
<span className="absolute inset-x-1 top-1 h-2 rounded-full bg-white/35 blur-[1px] transition-colors group-hover:bg-white/50" />
|
||||
<span className="absolute left-1/2 top-1/2 z-10 w-12 -translate-x-1/2 -translate-y-1/2 text-center uppercase leading-none tracking-tight text-white drop-shadow">
|
||||
<span className="absolute left-1/2 top-1/2 z-10 w-12 -translate-x-1/2 -translate-y-1/2 text-center uppercase leading-none tracking-tight text-white drop-shadow-sm">
|
||||
{translate('::App.Demos')}
|
||||
</span>
|
||||
</span>
|
||||
|
|
@ -276,7 +276,7 @@ export const PublicNav = ({
|
|||
return (
|
||||
<div key={item.code} className="group/menu relative">
|
||||
{renderItem(item)}
|
||||
<div className="invisible absolute left-0 top-full z-20 min-w-[13rem] rounded-lg border border-white/10 bg-gray-950/98 py-2 opacity-0 shadow-xl backdrop-blur-md transition-all duration-150 group-hover/menu:visible group-hover/menu:opacity-100">
|
||||
<div className="invisible absolute left-0 top-full z-20 min-w-52 rounded-lg border border-white/10 bg-gray-950/98 py-2 opacity-0 shadow-xl backdrop-blur-md transition-all duration-150 group-hover/menu:visible group-hover/menu:opacity-100">
|
||||
{item.children.map((child) => renderItem(child, 'px-4 py-2'))}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ export type ScriptBuilderDialogProps = {
|
|||
}
|
||||
|
||||
const controlClass =
|
||||
'w-full min-w-0 h-8 px-2 rounded border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-100 focus:outline-none focus:border-indigo-400'
|
||||
'w-full min-w-0 h-8 px-2 rounded-sm border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 text-sm text-gray-700 dark:text-gray-100 focus:outline-hidden focus:border-indigo-400'
|
||||
|
||||
const cardClass =
|
||||
'rounded-lg border border-gray-200 bg-white shadow-sm dark:border-gray-700 dark:bg-gray-900'
|
||||
'rounded-lg border border-gray-200 bg-white shadow-xs dark:border-gray-700 dark:bg-gray-900'
|
||||
|
||||
const editorOptions = {
|
||||
automaticLayout: true,
|
||||
|
|
@ -427,7 +427,7 @@ function ScriptBuilderDialog({
|
|||
}))
|
||||
|
||||
/** Ayar satirindaki her alan ayni yukseklikte, dar panelde alt satira sarar. */
|
||||
const fieldClass = 'min-w-0 basis-[9.5rem] grow'
|
||||
const fieldClass = 'min-w-0 basis-38 grow'
|
||||
|
||||
const fieldLabel = (text: string, title?: string) => (
|
||||
<span className="mb-1 block truncate text-xs text-gray-500" title={title}>
|
||||
|
|
@ -446,7 +446,7 @@ function ScriptBuilderDialog({
|
|||
return (
|
||||
<Fragment key={index}>
|
||||
{index > 0 ? (
|
||||
<label className="min-w-0 basis-[6.5rem] grow-0">
|
||||
<label className="min-w-0 basis-26 grow-0">
|
||||
{fieldLabel(translate('::App.ScriptBuilder.Conjunction'))}
|
||||
<Select
|
||||
size="sm"
|
||||
|
|
@ -574,14 +574,14 @@ function ScriptBuilderDialog({
|
|||
</div>
|
||||
</div>
|
||||
{conditions.length > 1 && (
|
||||
<span className="shrink-0 rounded-full bg-violet-100 px-2 py-[1px] text-[11px] text-violet-700 dark:bg-violet-900 dark:text-violet-200">
|
||||
<span className="shrink-0 rounded-full bg-violet-100 px-2 py-px text-[11px] text-violet-700 dark:bg-violet-900 dark:text-violet-200">
|
||||
{translate('::App.ScriptBuilder.ConditionCount', { count: conditions.length })} ·{' '}
|
||||
{translate(rule.join === 'or' ? '::App.Platform.Or' : '::App.Platform.And')}
|
||||
</span>
|
||||
)}
|
||||
{triggerInfo && trigger !== dialect.triggers?.[0]?.value && (
|
||||
<span
|
||||
className="shrink-0 rounded-full bg-sky-100 px-2 py-[1px] text-[11px] text-sky-700 dark:bg-sky-900 dark:text-sky-200"
|
||||
className="shrink-0 rounded-full bg-sky-100 px-2 py-px text-[11px] text-sky-700 dark:bg-sky-900 dark:text-sky-200"
|
||||
title={triggerInfo.help}
|
||||
>
|
||||
{triggerInfo.label}
|
||||
|
|
@ -589,7 +589,7 @@ function ScriptBuilderDialog({
|
|||
)}
|
||||
{!complete && (
|
||||
<span
|
||||
className="flex shrink-0 items-center gap-1 rounded-full bg-amber-100 px-2 py-[1px] text-[11px] text-amber-700 dark:bg-amber-900 dark:text-amber-200"
|
||||
className="flex shrink-0 items-center gap-1 rounded-full bg-amber-100 px-2 py-px text-[11px] text-amber-700 dark:bg-amber-900 dark:text-amber-200"
|
||||
title={
|
||||
dialect.getRuleWarning?.(rule) ||
|
||||
translate('::App.ScriptBuilder.IncompleteRuleWarning')
|
||||
|
|
@ -671,7 +671,7 @@ function ScriptBuilderDialog({
|
|||
{recipe.params.map((param) => renderParam(rule, param))}
|
||||
</div>
|
||||
|
||||
<pre className="mt-3 overflow-x-auto rounded border border-gray-100 bg-gray-950 px-3 py-2 font-mono text-[11px] text-emerald-100 dark:border-gray-800">
|
||||
<pre className="mt-3 overflow-x-auto rounded-sm border border-gray-100 bg-gray-950 px-3 py-2 font-mono text-[11px] text-emerald-100 dark:border-gray-800">
|
||||
{dialect.buildRuleLine(rule, rules) || recipe.example}
|
||||
</pre>
|
||||
</div>
|
||||
|
|
@ -686,7 +686,7 @@ function ScriptBuilderDialog({
|
|||
<FaSearch className="text-gray-400" size={11} />
|
||||
<Input
|
||||
unstyle
|
||||
className="w-full min-w-0 bg-transparent text-xs text-gray-700 outline-none dark:text-gray-100"
|
||||
className="w-full min-w-0 bg-transparent text-xs text-gray-700 outline-hidden dark:text-gray-100"
|
||||
placeholder={translate('::App.ScriptBuilder.SearchHelp')}
|
||||
value={helpSearch}
|
||||
onChange={(event) => setHelpSearch(event.target.value)}
|
||||
|
|
@ -710,7 +710,7 @@ function ScriptBuilderDialog({
|
|||
<button
|
||||
key={snippet.label}
|
||||
type="button"
|
||||
className="rounded border border-gray-100 px-2 py-1.5 text-left hover:border-indigo-300 hover:bg-indigo-50 dark:border-gray-800 dark:hover:bg-gray-800"
|
||||
className="rounded-sm border border-gray-100 px-2 py-1.5 text-left hover:border-indigo-300 hover:bg-indigo-50 dark:border-gray-800 dark:hover:bg-gray-800"
|
||||
title={`${snippet.description}\n\n${snippet.code}`}
|
||||
onClick={() => insertAtCursor(editorRef.current, snippet.code)}
|
||||
>
|
||||
|
|
@ -734,7 +734,7 @@ function ScriptBuilderDialog({
|
|||
<button
|
||||
key={entry.signature}
|
||||
type="button"
|
||||
className="rounded px-1 py-1 text-left hover:bg-indigo-50 dark:hover:bg-gray-800"
|
||||
className="rounded-sm px-1 py-1 text-left hover:bg-indigo-50 dark:hover:bg-gray-800"
|
||||
title={entry.description}
|
||||
onClick={() => insertAtCursor(editorRef.current, apiEntryName(entry))}
|
||||
>
|
||||
|
|
@ -767,10 +767,10 @@ function ScriptBuilderDialog({
|
|||
{/*
|
||||
Yükseklik zinciri iki yerden kopuyordu: Dialog'un `height` prop'u yalnızca
|
||||
react-modal içeriğine uygulanıyor, ve `.dialog-body` global olarak `flex-1`
|
||||
alıyor. `!flex-none` ile flex boyutlandırmasını kapatıp yüksekliği
|
||||
alıyor. `flex-none!` ile flex boyutlandırmasını kapatıp yüksekliği
|
||||
doğrudan veriyoruz.
|
||||
*/}
|
||||
<Dialog.Body className="flex h-[calc(100vh-16rem)] max-h-[calc(90vh-7rem)] min-h-[320px] !flex-none flex-col gap-3 !overflow-hidden mt-5">
|
||||
<Dialog.Body className="flex h-[calc(100vh-16rem)] max-h-[calc(90vh-7rem)] min-h-[320px] flex-none! flex-col gap-3 overflow-hidden! mt-5">
|
||||
<div className="flex flex-wrap items-center gap-2 border-b border-gray-200 pb-3 dark:border-gray-700">
|
||||
<FaCode className="text-indigo-500" />
|
||||
<h5 className="mr-1">{dialect.title}</h5>
|
||||
|
|
|
|||
|
|
@ -34,10 +34,10 @@ const AdaptableCard = (props: AdaptableCardProps) => {
|
|||
type === LAYOUT_TYPE_MODERN && 'border-0',
|
||||
type === LAYOUT_TYPE_MODERN &&
|
||||
rightSideBorder &&
|
||||
'ltr:border-r-0 rtl:border-l-0 ltr:md:border-r rtl:md:border-l md:border-gray-200 md:dark:border-gray-600 rounded-tr-none rounded-br-none rtl:rounded-tr-none rtl:rounded-br-none',
|
||||
'ltr:border-r-0 rtl:border-l-0 md:ltr:border-r md:rtl:border-l md:border-gray-200 md:dark:border-gray-600 rounded-tr-none rounded-br-none rtl:rounded-tr-none rtl:rounded-br-none',
|
||||
type === LAYOUT_TYPE_MODERN &&
|
||||
leftSideBorder &&
|
||||
'ltr:border-l-0 rtl:border-r-0 ltr:md:border-l rtl:md:border-r md:border-gray-200 md:dark:border-gray-600 rounded-tl-none rounded-bl-none rtl:rounded-tl-none rtl:rounded-bl-none',
|
||||
'ltr:border-l-0 rtl:border-r-0 md:ltr:border-l md:rtl:border-r md:border-gray-200 md:dark:border-gray-600 rounded-tl-none rounded-bl-none rtl:rounded-tl-none rtl:rounded-bl-none',
|
||||
type === LAYOUT_TYPE_MODERN &&
|
||||
divider &&
|
||||
`${
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ const BarcodeScannerDialog = ({
|
|||
<p className="mb-1 text-sm font-semibold">
|
||||
{translate('::App.BarcodeScanner.ScannedCount')}: {scanned.length}
|
||||
</p>
|
||||
<ul className="max-h-32 overflow-auto rounded border text-sm">
|
||||
<ul className="max-h-32 overflow-auto rounded-sm border text-sm">
|
||||
{scanned.map((code, index) => (
|
||||
<li key={`${code}-${index}`} className="border-b px-2 py-1 last:border-b-0">
|
||||
{code}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ const BarcodeViewer = ({
|
|||
// kaçışlanarak yazılır, bu yüzden gömmek güvenlidir.
|
||||
dangerouslySetInnerHTML={{ __html: svg }}
|
||||
className={classNames(
|
||||
'inline-block rounded bg-white p-2',
|
||||
'inline-block rounded-sm bg-white p-2',
|
||||
fitWidth && 'block w-full [&>svg]:h-auto [&>svg]:w-full',
|
||||
)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,306 +0,0 @@
|
|||
import type { CheckboxProps } from '@/components/ui/Checkbox'
|
||||
import Checkbox from '@/components/ui/Checkbox'
|
||||
import Pagination from '@/components/ui/Pagination'
|
||||
import Select from '@/components/ui/Select'
|
||||
import type { SkeletonProps } from '@/components/ui/Skeleton'
|
||||
import Table from '@/components/ui/Table'
|
||||
import {
|
||||
CellContext,
|
||||
ColumnDef,
|
||||
ColumnSort,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
Row,
|
||||
useReactTable,
|
||||
} from '@tanstack/react-table'
|
||||
import classNames from 'classnames'
|
||||
import type { ChangeEvent, ForwardedRef } from 'react'
|
||||
import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'
|
||||
import TableRowSkeleton from './loaders/TableRowSkeleton'
|
||||
import Loading from './Loading'
|
||||
|
||||
export type OnSortParam = { order: 'asc' | 'desc' | ''; key: string | number }
|
||||
|
||||
type DataTableProps<T> = {
|
||||
columns: ColumnDef<T>[]
|
||||
data?: unknown[]
|
||||
loading?: boolean
|
||||
onCheckBoxChange?: (checked: boolean, row: T) => void
|
||||
onIndeterminateCheckBoxChange?: (checked: boolean, rows: Row<T>[]) => void
|
||||
onPaginationChange?: (page: number) => void
|
||||
onSelectChange?: (num: number) => void
|
||||
onSort?: (sort: OnSortParam) => void
|
||||
pageSizes?: number[]
|
||||
selectable?: boolean
|
||||
skeletonAvatarColumns?: number[]
|
||||
skeletonAvatarProps?: SkeletonProps
|
||||
pagingData?: {
|
||||
total: number
|
||||
pageIndex: number
|
||||
pageSize: number
|
||||
}
|
||||
}
|
||||
|
||||
type CheckBoxChangeEvent = ChangeEvent<HTMLInputElement>
|
||||
|
||||
interface IndeterminateCheckboxProps extends Omit<CheckboxProps, 'onChange'> {
|
||||
onChange: (event: CheckBoxChangeEvent) => void
|
||||
indeterminate: boolean
|
||||
onCheckBoxChange?: (event: CheckBoxChangeEvent) => void
|
||||
onIndeterminateCheckBoxChange?: (event: CheckBoxChangeEvent) => void
|
||||
}
|
||||
|
||||
const { Tr, Th, Td, THead, TBody, Sorter } = Table
|
||||
|
||||
const IndeterminateCheckbox = (props: IndeterminateCheckboxProps) => {
|
||||
const { indeterminate, onChange, onCheckBoxChange, onIndeterminateCheckBoxChange, ...rest } =
|
||||
props
|
||||
|
||||
const ref = useRef<HTMLInputElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof indeterminate === 'boolean' && ref.current) {
|
||||
ref.current.indeterminate = !rest.checked && indeterminate
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [ref, indeterminate])
|
||||
|
||||
const handleChange = (e: CheckBoxChangeEvent) => {
|
||||
onChange(e)
|
||||
onCheckBoxChange?.(e)
|
||||
onIndeterminateCheckBoxChange?.(e)
|
||||
}
|
||||
|
||||
return <Checkbox ref={ref} className="mb-0" onChange={(_, e) => handleChange(e)} {...rest} />
|
||||
}
|
||||
|
||||
export type DataTableResetHandle = {
|
||||
resetSorting: () => void
|
||||
resetSelected: () => void
|
||||
}
|
||||
|
||||
function DataTableBase<T>(props: DataTableProps<T>, ref: ForwardedRef<DataTableResetHandle>) {
|
||||
const {
|
||||
skeletonAvatarColumns,
|
||||
columns: columnsProp = [],
|
||||
data = [],
|
||||
loading = false,
|
||||
onCheckBoxChange,
|
||||
onIndeterminateCheckBoxChange,
|
||||
onPaginationChange,
|
||||
onSelectChange,
|
||||
onSort,
|
||||
pageSizes = [10, 25, 50, 100],
|
||||
selectable = false,
|
||||
skeletonAvatarProps,
|
||||
pagingData = {
|
||||
total: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
} = props
|
||||
|
||||
const { pageSize, pageIndex, total } = pagingData
|
||||
|
||||
const [sorting, setSorting] = useState<ColumnSort[] | null>(null)
|
||||
|
||||
const pageSizeOption = useMemo(
|
||||
() =>
|
||||
pageSizes.map((number) => ({
|
||||
value: number,
|
||||
label: `${number} / page`,
|
||||
})),
|
||||
[pageSizes],
|
||||
)
|
||||
|
||||
const handleCheckBoxChange = (checked: boolean, row: T) => {
|
||||
if (!loading) {
|
||||
onCheckBoxChange?.(checked, row)
|
||||
}
|
||||
}
|
||||
|
||||
const handleIndeterminateCheckBoxChange = (checked: boolean, rows: Row<T>[]) => {
|
||||
if (!loading) {
|
||||
onIndeterminateCheckBoxChange?.(checked, rows)
|
||||
}
|
||||
}
|
||||
|
||||
const handlePaginationChange = (page: number) => {
|
||||
if (!loading) {
|
||||
onPaginationChange?.(page)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSelectChange = (value?: number) => {
|
||||
if (!loading) {
|
||||
onSelectChange?.(Number(value))
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (Array.isArray(sorting)) {
|
||||
const sortOrder = sorting.length > 0 ? (sorting[0].desc ? 'desc' : 'asc') : ''
|
||||
const id = sorting.length > 0 ? sorting[0].id : ''
|
||||
onSort?.({ order: sortOrder, key: id })
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [sorting])
|
||||
|
||||
const finalColumns: ColumnDef<T>[] = useMemo(() => {
|
||||
const columns = columnsProp
|
||||
|
||||
if (selectable) {
|
||||
return [
|
||||
{
|
||||
id: 'select',
|
||||
header: ({ table }) => (
|
||||
<IndeterminateCheckbox
|
||||
checked={table.getIsAllRowsSelected()}
|
||||
indeterminate={table.getIsSomeRowsSelected()}
|
||||
onChange={table.getToggleAllRowsSelectedHandler()}
|
||||
onIndeterminateCheckBoxChange={(e) => {
|
||||
handleIndeterminateCheckBoxChange(e.target.checked, table.getRowModel().rows)
|
||||
}}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }) => (
|
||||
<IndeterminateCheckbox
|
||||
checked={row.getIsSelected()}
|
||||
disabled={!row.getCanSelect()}
|
||||
indeterminate={row.getIsSomeSelected()}
|
||||
onChange={row.getToggleSelectedHandler()}
|
||||
onCheckBoxChange={(e) => handleCheckBoxChange(e.target.checked, row.original)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
...columns,
|
||||
]
|
||||
}
|
||||
return columns
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [columnsProp, selectable])
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns: finalColumns as ColumnDef<unknown | object | any[], any>[],
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
manualPagination: true,
|
||||
manualSorting: true,
|
||||
onSortingChange: (sorter) => {
|
||||
setSorting(sorter as ColumnSort[])
|
||||
},
|
||||
// Satir secimi tablonun kendi durumunda tutulur. Disaridan kontrol edilen bir
|
||||
// `rowSelection` degeri `onRowSelectionChange` olmadan degisimi yutuyor, onay kutusu
|
||||
// hicbir zaman isaretlenmiyordu; secilen satirlari cagiran taraf `onCheckBoxChange`
|
||||
// ile zaten kendi durumunda biriktiriyor.
|
||||
state: {
|
||||
sorting: sorting as ColumnSort[],
|
||||
},
|
||||
})
|
||||
|
||||
const resetSorting = () => {
|
||||
table.resetSorting()
|
||||
}
|
||||
|
||||
const resetSelected = () => {
|
||||
table.toggleAllRowsSelected(false)
|
||||
}
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
resetSorting,
|
||||
resetSelected,
|
||||
}))
|
||||
|
||||
return (
|
||||
<Loading loading={loading && data.length !== 0} type="cover">
|
||||
<Table>
|
||||
<THead>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<Tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<Th key={header.id} colSpan={header.colSpan}>
|
||||
{header.isPlaceholder ? null : (
|
||||
<div
|
||||
className={classNames(
|
||||
header.column.getCanSort() && 'cursor-pointer select-none point',
|
||||
loading && 'pointer-events-none',
|
||||
)}
|
||||
onClick={header.column.getToggleSortingHandler()}
|
||||
>
|
||||
{flexRender(header.column.columnDef.header, header.getContext())}
|
||||
{header.column.getCanSort() && (
|
||||
<Sorter sort={header.column.getIsSorted()} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Th>
|
||||
)
|
||||
})}
|
||||
</Tr>
|
||||
))}
|
||||
</THead>
|
||||
{loading && data.length === 0 ? (
|
||||
<TableRowSkeleton
|
||||
columns={(finalColumns as Array<T>).length}
|
||||
rows={pagingData.pageSize}
|
||||
avatarInColumns={skeletonAvatarColumns}
|
||||
avatarProps={skeletonAvatarProps}
|
||||
/>
|
||||
) : (
|
||||
<TBody>
|
||||
{table
|
||||
.getRowModel()
|
||||
.rows.slice(0, pageSize)
|
||||
.map((row) => {
|
||||
return (
|
||||
<Tr key={row.id}>
|
||||
{row.getVisibleCells().map((cell) => {
|
||||
return (
|
||||
<Td key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</Td>
|
||||
)
|
||||
})}
|
||||
</Tr>
|
||||
)
|
||||
})}
|
||||
</TBody>
|
||||
)}
|
||||
</Table>
|
||||
<div className="flex items-center justify-between mt-4">
|
||||
<Pagination
|
||||
pageSize={pageSize}
|
||||
currentPage={pageIndex}
|
||||
total={total}
|
||||
onChange={handlePaginationChange}
|
||||
/>
|
||||
<div style={{ minWidth: 130 }}>
|
||||
<Select
|
||||
size="sm"
|
||||
menuPlacement="top"
|
||||
isSearchable={false}
|
||||
value={pageSizeOption.filter((option) => option.value === pageSize)}
|
||||
options={pageSizeOption}
|
||||
onChange={(option) => handleSelectChange(option?.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Loading>
|
||||
)
|
||||
}
|
||||
|
||||
const DataTable = forwardRef(DataTableBase) as <T>(
|
||||
props: DataTableProps<T> & {
|
||||
ref?: ForwardedRef<DataTableResetHandle>
|
||||
},
|
||||
) => ReturnType<typeof DataTableBase>
|
||||
|
||||
export type { CellContext, ColumnDef, Row }
|
||||
export default DataTable
|
||||
|
|
@ -46,7 +46,7 @@ function DbMigrateLogPanel({ title, onClose }: DbMigrateLogPanelProps) {
|
|||
}, [logs])
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/60">
|
||||
<div className="fixed inset-0 z-9999 flex items-center justify-center bg-black/60">
|
||||
<div className="flex flex-col w-[900px] max-w-[95vw] h-[520px] max-h-[90vh] rounded-xl shadow-2xl bg-gray-900 border border-gray-700">
|
||||
<div className="flex items-center justify-between px-4 py-3 border-b border-gray-700">
|
||||
<span className="text-white font-semibold text-sm">{title}</span>
|
||||
|
|
@ -59,7 +59,7 @@ function DbMigrateLogPanel({ title, onClose }: DbMigrateLogPanelProps) {
|
|||
<Button
|
||||
variant="default"
|
||||
size="xs"
|
||||
className="!bg-gray-800 !border-gray-600 !text-gray-300 hover:!bg-gray-700 hover:!border-gray-400 hover:!text-white"
|
||||
className="bg-gray-800! border-gray-600! text-gray-300! hover:bg-gray-700! hover:border-gray-400! hover:text-white!"
|
||||
onClick={onClose}
|
||||
>
|
||||
Close
|
||||
|
|
@ -68,7 +68,7 @@ function DbMigrateLogPanel({ title, onClose }: DbMigrateLogPanelProps) {
|
|||
</div>
|
||||
<div className="flex-1 overflow-y-auto p-3 font-mono text-xs leading-relaxed">
|
||||
{logs.map((log, i) => (
|
||||
<div key={i} className={`whitespace-pre-wrap break-words ${levelColor(log.level)}`}>
|
||||
<div key={i} className={`whitespace-pre-wrap wrap-break-word ${levelColor(log.level)}`}>
|
||||
<span className="text-gray-500 mr-2 select-none">{String(i + 1).padStart(4, '0')}</span>
|
||||
{log.message}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ const CoveredLoading = (props: BaseLoadingProps) => {
|
|||
<Component className={classNames(loading ? 'relative' : '', className)}>
|
||||
{children}
|
||||
{loading && (
|
||||
<div className="w-full h-full bg-white dark:bg-gray-800 dark:bg-opacity-60 bg-opacity-50 absolute inset-0" />
|
||||
<div className="w-full h-full bg-white/50 dark:bg-gray-800/60 absolute inset-0" />
|
||||
)}
|
||||
{loading && (
|
||||
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 z-10">
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ const withCode = (text: string, keyPrefix: string): ReactNode[] =>
|
|||
const rest = part.slice(trimmed.length)
|
||||
return (
|
||||
<Fragment key={`${keyPrefix}-c${index}`}>
|
||||
<code className="rounded bg-gray-100 px-1 py-0.5 font-mono text-[0.9em] text-gray-800 dark:bg-gray-700 dark:text-gray-100">
|
||||
<code className="rounded-sm bg-gray-100 px-1 py-0.5 font-mono text-[0.9em] text-gray-800 dark:bg-gray-700 dark:text-gray-100">
|
||||
{trimmed}
|
||||
</code>
|
||||
{rest}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,11 @@ export { default as BarcodeViewer } from './BarcodeViewer'
|
|||
export { default as PermissionCheck } from './PermissionCheck'
|
||||
export { default as ConfirmDialog } from './ConfirmDialog'
|
||||
export { default as Container } from './Container'
|
||||
export { default as DataTable } from './DataTable'
|
||||
export { default as DoubleSidedImage } from './DoubleSidedImage'
|
||||
export { default as Loading } from './Loading'
|
||||
export { default as NavToggle } from './NavToggle'
|
||||
export { default as PasswordInput } from './PasswordInput'
|
||||
export { default as RichText } from './RichText'
|
||||
export { default as SegmentItemOption } from './SegmentItemOption'
|
||||
export { default as TableRowSkeleton } from './loaders/TableRowSkeleton'
|
||||
export { default as TenantSelector } from './TenantSelector'
|
||||
|
||||
export type { DataTableResetHandle, OnSortParam, ColumnDef, Row, CellContext } from './DataTable'
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
import Skeleton from '@/components/ui/Skeleton'
|
||||
import Table from '@/components/ui/Table'
|
||||
import type { SkeletonProps } from '@/components/ui/Skeleton'
|
||||
|
||||
type TableRowSkeletonProps = {
|
||||
columns?: number
|
||||
rows?: number
|
||||
avatarInColumns?: number[]
|
||||
avatarProps?: SkeletonProps
|
||||
}
|
||||
|
||||
const { Tr, Td, TBody } = Table
|
||||
|
||||
const TableRowSkeleton = (props: TableRowSkeletonProps) => {
|
||||
const { columns = 1, rows = 10, avatarInColumns = [], avatarProps } = props
|
||||
|
||||
return (
|
||||
<TBody>
|
||||
{Array.from(new Array(rows), (_, i) => i + 0).map((row) => (
|
||||
<Tr key={`row-${row}`}>
|
||||
{Array.from(new Array(columns), (_, i) => i + 0).map(
|
||||
(col) => (
|
||||
<Td key={`col-${col}`}>
|
||||
<div className="flex flex-auto items-center gap-2">
|
||||
{avatarInColumns.includes(col) && (
|
||||
<div>
|
||||
<Skeleton
|
||||
variant="circle"
|
||||
{...avatarProps}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Skeleton />
|
||||
</div>
|
||||
</Td>
|
||||
)
|
||||
)}
|
||||
</Tr>
|
||||
))}
|
||||
</TBody>
|
||||
)
|
||||
}
|
||||
|
||||
export default TableRowSkeleton
|
||||
|
|
@ -50,7 +50,7 @@ const LanguageSelectorBase = ({ className }: CommonProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<Dropdown renderTitle={selectedLanguage} placement="bottom-start" menuClass="z-[60]">
|
||||
<Dropdown renderTitle={selectedLanguage} placement="bottom-start" menuClass="z-60">
|
||||
{languageList?.map((lang) => (
|
||||
<Dropdown.Item
|
||||
key={lang.cultureName}
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
if (!auth.session.signedIn || !location.pathname.startsWith('/admin')) return null
|
||||
|
||||
const panelClassName =
|
||||
'pointer-events-auto fixed inset-2 z-[51] overflow-hidden rounded-xl border border-gray-200 bg-white/80 shadow-[0_24px_80px_rgba(15,23,42,0.35)] backdrop-blur-xl dark:border-gray-700 dark:bg-gray-900/85 sm:inset-4'
|
||||
'pointer-events-auto fixed inset-2 z-51 overflow-hidden rounded-xl border border-gray-200 bg-white/80 shadow-[0_24px_80px_rgba(15,23,42,0.35)] backdrop-blur-xl dark:border-gray-700 dark:bg-gray-900/85 sm:inset-4'
|
||||
|
||||
const headerActionClassName =
|
||||
'text-gray-600 hover:bg-gray-900/10 hover:text-gray-900 active:bg-gray-900/15 dark:text-gray-200 dark:hover:bg-white/10 dark:hover:text-white dark:active:bg-white/15'
|
||||
|
|
@ -380,7 +380,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
aria-label={translate('::App.MessengerWidget.Minimize')}
|
||||
variant="plain"
|
||||
shape="none"
|
||||
className="fixed inset-0 z-50 !h-auto cursor-default bg-slate-950/25 !px-0 backdrop-blur-[1px] hover:!bg-slate-950/25 active:!bg-slate-950/25 dark:bg-black/55 dark:hover:!bg-black/55 dark:active:!bg-black/55"
|
||||
className="fixed inset-0 z-50 h-auto! cursor-default bg-slate-950/25 px-0! backdrop-blur-[1px] hover:bg-slate-950/25! active:bg-slate-950/25! dark:bg-black/55 dark:hover:bg-black/55! dark:active:bg-black/55!"
|
||||
onClick={closeWidget}
|
||||
/>
|
||||
<div className={panelClassName} role="dialog" aria-modal="true">
|
||||
|
|
@ -429,7 +429,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
</div>
|
||||
|
||||
<div className="flex items-center gap-2 p-3">
|
||||
<div className="min-w-0 flex-[6]">
|
||||
<div className="min-w-0 flex-6">
|
||||
<Input
|
||||
size="sm"
|
||||
value={filter}
|
||||
|
|
@ -465,7 +465,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
variant="plain"
|
||||
shape="none"
|
||||
block
|
||||
className={`mb-1 !flex !h-auto items-center gap-3 !rounded-md !px-2 !py-2 text-left transition ${
|
||||
className={`mb-1 !flex h-auto! items-center gap-3 rounded-md! px-2! py-2! text-left transition ${
|
||||
active
|
||||
? 'bg-emerald-50 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-100'
|
||||
: 'hover:bg-white dark:hover:bg-gray-800'
|
||||
|
|
@ -593,7 +593,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
className={`group flex max-w-[76%] items-start gap-1.5 ${own ? 'flex-row-reverse' : ''}`}
|
||||
>
|
||||
<div
|
||||
className={`rounded-lg px-3 py-2 shadow-sm ${
|
||||
className={`rounded-lg px-3 py-2 shadow-xs ${
|
||||
own
|
||||
? 'bg-emerald-600 text-white'
|
||||
: 'bg-gray-100 text-gray-900 dark:bg-gray-700 dark:text-gray-100'
|
||||
|
|
@ -660,7 +660,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
variant="plain"
|
||||
shape="circle"
|
||||
icon={<FaTrash />}
|
||||
className="mt-1 !h-5 !w-5 shrink-0 !px-0 text-[10px] text-gray-400 opacity-0 transition hover:!bg-red-500 hover:text-white group-hover:opacity-100 focus:opacity-100"
|
||||
className="mt-1 h-5! w-5! shrink-0 px-0! text-[10px] text-gray-400 opacity-0 transition hover:bg-red-500! hover:text-white group-hover:opacity-100 focus:opacity-100"
|
||||
onClick={() => deleteMessage(message.id)}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -685,7 +685,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
variant="plain"
|
||||
shape="circle"
|
||||
icon={<FaTrash />}
|
||||
className="!h-5 !w-5 shrink-0 !px-0 text-gray-500 hover:text-red-500"
|
||||
className="h-5! w-5! shrink-0 px-0! text-gray-500 hover:text-red-500"
|
||||
onClick={() =>
|
||||
setAttachments((prev) =>
|
||||
prev.filter((item) => item.savedFileName !== file.savedFileName),
|
||||
|
|
@ -703,9 +703,10 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
<div className="absolute bottom-16 left-2 z-10 sm:left-10">
|
||||
<Suspense fallback={<div className="h-[380px] w-[320px] max-w-[calc(100vw-32px)]" />}>
|
||||
<EmojiPicker
|
||||
onEmojiClick={onEmojiClick}
|
||||
width="min(320px, calc(100vw - 32px))"
|
||||
emojiStyle="apple"
|
||||
height={380}
|
||||
width="min(320px, calc(100vw - 32px))"
|
||||
onEmojiClick={onEmojiClick}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
|
|
@ -751,7 +752,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
}
|
||||
rows={1}
|
||||
disabled={!canSendToSelectedContacts}
|
||||
className="min-h-[36px] flex-1 resize-none border-0 bg-transparent px-2 py-2 text-sm text-gray-900 outline-none placeholder:text-gray-400 focus:ring-0 dark:text-gray-100"
|
||||
className="min-h-[36px] flex-1 resize-none border-0 bg-transparent px-2 py-2 text-sm text-gray-900 outline-hidden placeholder:text-gray-400 focus:ring-0 dark:text-gray-100"
|
||||
onChange={(event) => setText(event.target.value)}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
|
|
@ -785,7 +786,7 @@ const MessengerWidgetContent = ({ className }: { className?: string }) => {
|
|||
className={classNames(
|
||||
className,
|
||||
textTheme,
|
||||
'pointer-events-auto relative !mx-0 text-2xl transition-colors duration-300 ease-in-out hover:bg-black hover:bg-opacity-5 dark:hover:bg-black dark:hover:bg-opacity-40',
|
||||
'pointer-events-auto relative mx-0! text-2xl transition-colors duration-300 ease-in-out hover:bg-black/5 dark:hover:bg-black/40',
|
||||
)}
|
||||
aria-label={translate('::App.MessengerWidget.Title')}
|
||||
role="button"
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ type NotificationListItem = {
|
|||
readed: boolean
|
||||
}
|
||||
|
||||
const notificationHeight = 'h-[26rem]'
|
||||
const notificationHeight = 'h-104'
|
||||
/** SignalR duyurusu kaybolursa devreye giren yedek yoklama aralığı. */
|
||||
const notificationInterval = 300000 // 5 minutes
|
||||
const foregroundPollThrottle = 30000 // 30 seconds
|
||||
|
|
@ -416,7 +416,7 @@ const NotificationDropdown = ({ className }: { className?: string }) => {
|
|||
{notificationList.map((item, index) => (
|
||||
<div
|
||||
key={item.ids[0]}
|
||||
className={`relative flex px-4 py-4 cursor-pointer hover:bg-gray-50 active:bg-gray-100 dark:hover:bg-black dark:hover:bg-opacity-20 ${
|
||||
className={`relative flex px-4 py-4 cursor-pointer hover:bg-gray-50 active:bg-gray-100 dark:hover:bg-black/20 ${
|
||||
!isLastChild(notificationList, index)
|
||||
? 'border-b border-gray-200 dark:border-gray-600'
|
||||
: ''
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ const ListItem = (props: {
|
|||
<div className="flex items-center">
|
||||
{/* <div
|
||||
className={classNames(
|
||||
'mr-4 rounded-md ring-1 ring-slate-900/5 shadow-sm text-xl group-hover:shadow h-6 w-6 flex items-center justify-center bg-white dark:bg-gray-700',
|
||||
'mr-4 rounded-md ring-1 ring-slate-900/5 shadow-xs text-xl group-hover:shadow-sm h-6 w-6 flex items-center justify-center bg-white dark:bg-gray-700',
|
||||
textTheme,
|
||||
'dark:text-gray-100',
|
||||
)}
|
||||
|
|
@ -193,7 +193,7 @@ const SearchBase = ({ className }: { className?: string }) => {
|
|||
<Input
|
||||
unstyle
|
||||
ref={inputRef}
|
||||
className="ring-0 outline-none block w-full p-4 text-base bg-transparent text-gray-900 dark:text-gray-100"
|
||||
className="ring-0 outline-hidden block w-full p-4 text-base bg-transparent text-gray-900 dark:text-gray-100"
|
||||
placeholder={translate('::App.Platform.Search2')}
|
||||
onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ const Alert = forwardRef<HTMLDivElement, AlertProps>((props, ref) => {
|
|||
{showIcon && <StatusIcon iconColor={typeMap.iconColor} custom={customIcon} type={type} />}
|
||||
<div
|
||||
className={classNames(
|
||||
'min-w-0 flex-1 whitespace-normal break-words leading-6',
|
||||
'min-w-0 flex-1 whitespace-normal wrap-break-word leading-6',
|
||||
showIcon ? 'ltr:ml-2 rtl:mr-2' : '',
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -107,12 +107,12 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
|
|||
const btn = {
|
||||
bgColor: active
|
||||
? `bg-${buttonColor}-200 dark:bg-${buttonColor}-50`
|
||||
: `bg-${buttonColor}-50 dark:bg-${buttonColor}-500 dark:bg-opacity-20`,
|
||||
: `bg-${buttonColor}-50 dark:bg-${buttonColor}-500/20`,
|
||||
textColor: `text-${buttonColor}-${buttonColorLevel} dark:text-${buttonColor}-50`,
|
||||
hoverColor: active
|
||||
? ''
|
||||
: `hover:bg-${buttonColor}-100 dark:hover:bg-${buttonColor}-500 dark:hover:bg-opacity-30`,
|
||||
activeColor: `active:bg-${buttonColor}-200 dark:active:bg-${buttonColor}-500 dark:active:bg-opacity-40`,
|
||||
: `hover:bg-${buttonColor}-100 dark:hover:bg-${buttonColor}-500/30`,
|
||||
activeColor: `active:bg-${buttonColor}-200 dark:active:bg-${buttonColor}-500/40`,
|
||||
}
|
||||
return getBtnColor(btn)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ const Day = forwardRef<HTMLButtonElement, DayProps>((props, ref) => {
|
|||
} = props
|
||||
|
||||
const { themeColor, primaryColorLevel } = useConfig()
|
||||
const inRangeOnly = inRange && !disabled && !firstInRange && !lastInRange && !selected
|
||||
|
||||
return (
|
||||
<button
|
||||
|
|
@ -78,6 +79,16 @@ const Day = forwardRef<HTMLButtonElement, DayProps>((props, ref) => {
|
|||
ref={ref}
|
||||
type="button"
|
||||
disabled={disabled}
|
||||
// Aralik gunu tema renginin %10'u: renk adi calisma aninda geldigi icin her renk/ton icin
|
||||
// ayri `/10` sinifi uretmek yerine temanin renk degiskeni kullanilir.
|
||||
style={
|
||||
inRangeOnly
|
||||
? {
|
||||
...others.style,
|
||||
backgroundColor: `color-mix(in oklab, var(--color-${themeColor}-${primaryColorLevel}) 10%, transparent)`,
|
||||
}
|
||||
: others.style
|
||||
}
|
||||
tabIndex={getDayTabIndex({
|
||||
focusable,
|
||||
hasValue,
|
||||
|
|
@ -102,12 +113,6 @@ const Day = forwardRef<HTMLButtonElement, DayProps>((props, ref) => {
|
|||
selected &&
|
||||
!disabled &&
|
||||
`bg-${themeColor}-${primaryColorLevel} text-gray-100`,
|
||||
inRange &&
|
||||
!disabled &&
|
||||
!firstInRange &&
|
||||
!lastInRange &&
|
||||
!selected &&
|
||||
`bg-${themeColor}-${primaryColorLevel} bg-opacity-10`,
|
||||
!inRange && !firstInRange && !lastInRange && 'rounded-lg',
|
||||
firstInRange &&
|
||||
!disabled &&
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import classNames from 'classnames'
|
|||
import ReactSelect, { components as ReactSelectComponents } from 'react-select'
|
||||
import CreatableSelect from 'react-select/creatable'
|
||||
import AsyncSelect from 'react-select/async'
|
||||
import { TW_COLORS, BORDER_RADIUS } from '@/utils/tailwind'
|
||||
import { themeColor as twColor } from '@/utils/tailwind'
|
||||
import { isEmpty, get } from '@/utils/collection'
|
||||
import { useConfig } from '../ConfigProvider'
|
||||
import { useForm } from '../Form/context'
|
||||
|
|
@ -173,8 +173,6 @@ function SelectBase<
|
|||
const selectSize = size || inputGroupSize || formControlSize || controlSize
|
||||
const sizeMetrics = SELECT_SIZE_METRICS[selectSize]
|
||||
|
||||
const twColor = TW_COLORS as any
|
||||
|
||||
let isInvalid = false
|
||||
|
||||
if (!isEmpty(form)) {
|
||||
|
|
@ -190,11 +188,11 @@ function SelectBase<
|
|||
const shadaowBase = '0 0 0 1px '
|
||||
|
||||
if (isInvalid) {
|
||||
return shadaowBase + twColor.red['500']
|
||||
return shadaowBase + twColor('red', 500)
|
||||
}
|
||||
|
||||
if (state.isFocused) {
|
||||
return shadaowBase + twColor[themeColor][primaryColorLevel]
|
||||
return shadaowBase + twColor(themeColor, primaryColorLevel)
|
||||
}
|
||||
|
||||
return 'none'
|
||||
|
|
@ -219,8 +217,8 @@ function SelectBase<
|
|||
cursor: 'pointer',
|
||||
},
|
||||
boxShadow: getBoxShadow(state),
|
||||
borderRadius: BORDER_RADIUS.md,
|
||||
...(isInvalid ? { borderColor: twColor.red['500'] } : {}),
|
||||
borderRadius: 'var(--radius-md)',
|
||||
...(isInvalid ? { borderColor: twColor('red', 500) } : {}),
|
||||
}
|
||||
},
|
||||
input: (css) => {
|
||||
|
|
@ -257,14 +255,14 @@ function SelectBase<
|
|||
...theme,
|
||||
colors: {
|
||||
...theme.colors,
|
||||
neutral0: mode === 'dark' ? twColor.gray['800'] : (TW_COLORS as any).white,
|
||||
neutral20: mode === 'dark' ? twColor.gray['600'] : twColor.gray['300'],
|
||||
neutral30: mode === 'dark' ? twColor.gray['600'] : twColor.gray['300'],
|
||||
neutral80: mode === 'dark' ? (TW_COLORS as any).white : twColor.gray['700'],
|
||||
neutral10: mode === 'dark' ? twColor.gray['600'] : twColor.gray['300'],
|
||||
primary25: twColor[themeColor]['50'],
|
||||
primary50: twColor[themeColor]['100'],
|
||||
primary: twColor[themeColor][primaryColorLevel],
|
||||
neutral0: mode === 'dark' ? twColor('gray', 800) : twColor('white'),
|
||||
neutral20: mode === 'dark' ? twColor('gray', 600) : twColor('gray', 300),
|
||||
neutral30: mode === 'dark' ? twColor('gray', 600) : twColor('gray', 300),
|
||||
neutral80: mode === 'dark' ? twColor('white') : twColor('gray', 700),
|
||||
neutral10: mode === 'dark' ? twColor('gray', 600) : twColor('gray', 300),
|
||||
primary25: twColor(themeColor, 50),
|
||||
primary50: twColor(themeColor, 100),
|
||||
primary: twColor(themeColor, primaryColorLevel),
|
||||
},
|
||||
})}
|
||||
themeColor={`${themeColor}-${primaryColorLevel}`}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default function Widget({
|
|||
<div
|
||||
onClick={onClick}
|
||||
className={classNames(
|
||||
'bg-white dark:bg-gray-900 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-4 flex flex-col justify-between',
|
||||
'bg-white dark:bg-gray-900 rounded-lg shadow-xs border border-gray-200 dark:border-gray-700 p-4 flex flex-col justify-between',
|
||||
onClick && 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800',
|
||||
className,
|
||||
)}
|
||||
|
|
@ -83,7 +83,7 @@ export default function Widget({
|
|||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
'w-12 h-12 bg-gradient-to-br rounded-xl flex items-center justify-center shadow-sm',
|
||||
'w-12 h-12 bg-linear-to-br rounded-xl flex items-center justify-center shadow-xs',
|
||||
colorMap[safeColor].bg,
|
||||
'dark:' + colorMap[safeColor].darkBg
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -701,7 +701,7 @@ const PlatformPlaceholder = ({ node }: { node: DesignerNode }) => {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`flex min-h-40 items-center justify-center rounded-lg border border-dashed border-sky-300 bg-gradient-to-br from-sky-50 to-indigo-50 p-6 text-center dark:border-sky-800 dark:from-slate-900 dark:to-sky-950 ${String(node.props.className || '')}`}
|
||||
className={`flex min-h-40 items-center justify-center rounded-lg border border-dashed border-sky-300 bg-linear-to-br from-sky-50 to-indigo-50 p-6 text-center dark:border-sky-800 dark:from-slate-900 dark:to-sky-950 ${String(node.props.className || '')}`}
|
||||
style={{ minHeight: String(node.props.height || '320px') }}
|
||||
>
|
||||
<div>
|
||||
|
|
@ -740,7 +740,7 @@ const GridColumnHeaders = ({ columns }: { columns: string[] }) => {
|
|||
const { translate } = useLocalization()
|
||||
|
||||
return (
|
||||
<div className="min-w-0 overflow-auto rounded-md border border-slate-200 bg-slate-100 [grid-column:1/-1] dark:border-slate-700 dark:bg-slate-800">
|
||||
<div className="min-w-0 overflow-auto rounded-md border border-slate-200 bg-slate-100 col-span-full dark:border-slate-700 dark:bg-slate-800">
|
||||
{columns.length ? (
|
||||
<div className="flex min-w-max divide-x divide-slate-200 dark:divide-slate-700">
|
||||
{columns.map((column) => (
|
||||
|
|
@ -797,7 +797,7 @@ const GridDataTablePreview = ({
|
|||
|
||||
if (!columns.length) {
|
||||
return (
|
||||
<div className="rounded-lg border border-dashed border-slate-300 bg-slate-50 p-4 text-center text-xs text-slate-500 [grid-column:1/-1] dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
|
||||
<div className="rounded-lg border border-dashed border-slate-300 bg-slate-50 p-4 text-center text-xs text-slate-500 col-span-full dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
|
||||
{translate('::App.VisualDesignerCanvas.SelectAtLeastOneColumn')}
|
||||
</div>
|
||||
)
|
||||
|
|
@ -805,7 +805,7 @@ const GridDataTablePreview = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`min-w-0 rounded-lg border border-slate-200 bg-white shadow-sm [grid-column:1/-1] dark:border-slate-700 dark:bg-slate-900 ${overflow ? 'overflow-auto' : 'overflow-visible'}`}
|
||||
className={`min-w-0 rounded-lg border border-slate-200 bg-white shadow-xs col-span-full dark:border-slate-700 dark:bg-slate-900 ${overflow ? 'overflow-auto' : 'overflow-visible'}`}
|
||||
>
|
||||
<table className={`w-full border-collapse text-left ${compact ? 'text-[11px]' : 'text-xs'}`}>
|
||||
<thead className="bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-200">
|
||||
|
|
@ -1006,7 +1006,7 @@ const FormView = ({
|
|||
? translate('::App.Platform.RecordCount', { count: rows.length })
|
||||
: translate('::App.VisualDesignerCanvas.NoSelectEndpoint')}
|
||||
</span>
|
||||
<span className="rounded bg-sky-600 px-1.5 py-0.5 font-semibold text-white">
|
||||
<span className="rounded-sm bg-sky-600 px-1.5 py-0.5 font-semibold text-white">
|
||||
{translate(
|
||||
mode === 'new' ? '::App.VisualDesignerCanvas.NewRecord' : '::App.Platform.Editing',
|
||||
)}
|
||||
|
|
@ -1016,7 +1016,7 @@ const FormView = ({
|
|||
{translate('::App.Platform.Row')}
|
||||
<UiKit.Select
|
||||
size="xs"
|
||||
className="min-w-[4.5rem]"
|
||||
className="min-w-18"
|
||||
maxMenuHeight={200}
|
||||
menuPosition="fixed"
|
||||
menuPortalTarget={window.document.body}
|
||||
|
|
@ -1049,7 +1049,7 @@ const FormView = ({
|
|||
)}
|
||||
{/* The drop zone belongs with the content, above the command toolbar. */}
|
||||
{interactive && !node.children.length && (
|
||||
<div className="rounded border border-dashed border-slate-300 px-3 py-4 text-center text-xs text-slate-400 dark:border-slate-700">
|
||||
<div className="rounded-sm border border-dashed border-slate-300 px-3 py-4 text-center text-xs text-slate-400 dark:border-slate-700">
|
||||
{translate('::App.VisualDesignerCanvas.DropAndBind')}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -1461,7 +1461,7 @@ const HOISTED_LAYOUT_EXACT = new Set([
|
|||
const SHARED_LAYOUT_PATTERN = /^(absolute|fixed|sticky|w-full|h-full)$|^-?(inset|top|right|bottom|left)-|^z-|^(min|max)-w-/
|
||||
const NODE_POSITION_PATTERN = /^(absolute|fixed|sticky)$/
|
||||
|
||||
/** `md:`, `dark:hover:` gibi varyant onlerini atar; `[grid-column:1/-1]` bozulmadan kalir. */
|
||||
/** `md:`, `dark:hover:` gibi varyant onlerini atar; `col-span-full` bozulmadan kalir. */
|
||||
const stripVariants = (token: string) => token.replace(/^(?:(?:[\w-]+|\[[^\]]+\]):)+/, '')
|
||||
|
||||
/**
|
||||
|
|
@ -1781,7 +1781,7 @@ const NodeView = ({
|
|||
<div
|
||||
className={`min-h-14 rounded py-2 transition ${
|
||||
overSlot === slot
|
||||
? 'bg-emerald-50 outline outline-2 outline-emerald-500 dark:bg-emerald-950/40'
|
||||
? 'bg-emerald-50 outline-solid outline-2 outline-emerald-500 dark:bg-emerald-950/40'
|
||||
: dragging
|
||||
? 'outline-dashed outline-1 outline-sky-400/70'
|
||||
: ''
|
||||
|
|
@ -1822,7 +1822,7 @@ const NodeView = ({
|
|||
/>
|
||||
))}
|
||||
{interactive && !tabNodes.length && !option.content && (
|
||||
<div className="flex min-h-12 items-center justify-center rounded border border-dashed border-slate-300 px-2 text-center text-[10px] text-slate-400 dark:border-slate-700">
|
||||
<div className="flex min-h-12 items-center justify-center rounded-sm border border-dashed border-slate-300 px-2 text-center text-[10px] text-slate-400 dark:border-slate-700">
|
||||
{translate('::App.VisualDesignerCanvas.DropComponentInTab')}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -1838,7 +1838,7 @@ const NodeView = ({
|
|||
node.type === 'Table' ? (
|
||||
<UiKit.Table
|
||||
borderlessRow
|
||||
className={`${String(node.props.className || '')} [&>tbody>tr>td]:!px-1.5 [&>tbody>tr>td]:!py-1.5`}
|
||||
className={`${String(node.props.className || '')} [&>tbody>tr>td]:px-1.5! [&>tbody>tr>td]:py-1.5!`}
|
||||
compact={Boolean(node.props.compact)}
|
||||
hoverable={node.props.hoverable !== false}
|
||||
overflow={node.props.overflow !== false}
|
||||
|
|
@ -1912,7 +1912,7 @@ const NodeView = ({
|
|||
/>
|
||||
))}
|
||||
{interactive && !cellNodes.length && (
|
||||
<div className="flex min-h-12 items-center justify-center rounded border border-dashed border-slate-300 px-2 text-center text-[10px] text-slate-400 dark:border-slate-700">
|
||||
<div className="flex min-h-12 items-center justify-center rounded-sm border border-dashed border-slate-300 px-2 text-center text-[10px] text-slate-400 dark:border-slate-700">
|
||||
{translate('::App.VisualDesignerCanvas.DropComponent')}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -1972,7 +1972,7 @@ const NodeView = ({
|
|||
? [
|
||||
<div
|
||||
key={`grid_loading_${node.id}`}
|
||||
className="rounded-lg border border-slate-200 bg-slate-50 p-4 text-center text-xs text-slate-500 [grid-column:1/-1] dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400"
|
||||
className="rounded-lg border border-slate-200 bg-slate-50 p-4 text-center text-xs text-slate-500 col-span-full dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400"
|
||||
>
|
||||
{translate('::App.VisualDesignerCanvas.LoadingData')}
|
||||
</div>,
|
||||
|
|
@ -2058,15 +2058,15 @@ const NodeView = ({
|
|||
isDragSource ? 'opacity-40' : ''
|
||||
} ${
|
||||
dropHint === 'inside'
|
||||
? 'z-10 bg-emerald-500/10 outline outline-2 outline-emerald-500 outline-offset-2'
|
||||
? 'z-10 bg-emerald-500/10 outline-solid outline-2 outline-emerald-500 outline-offset-2'
|
||||
: // Sürükleme sürerken içine bırakılabilen her konteyner işaretlenir, böylece
|
||||
// kullanıcı hedefe varmadan önce nereye bırakabileceğini görür.
|
||||
dragging && canDropInside
|
||||
? 'outline-dashed outline-1 outline-sky-400/70 outline-offset-2'
|
||||
: interactive
|
||||
? selected
|
||||
? 'z-10 outline outline-2 outline-sky-500 outline-offset-2'
|
||||
: 'outline outline-1 outline-transparent hover:outline-sky-300'
|
||||
? 'z-10 outline-solid outline-2 outline-sky-500 outline-offset-2'
|
||||
: 'outline-solid outline-1 outline-transparent hover:outline-sky-300'
|
||||
: ''
|
||||
}`}
|
||||
data-designer-node={node.id}
|
||||
|
|
@ -2122,28 +2122,28 @@ const NodeView = ({
|
|||
{/* Yanına bırakma çizgisi: bileşen tam olarak buraya girer. */}
|
||||
{dropHint === 'before' && (
|
||||
<div className="pointer-events-none absolute inset-x-0 -top-1 z-30 flex items-center gap-1">
|
||||
<span className="rounded bg-emerald-600 px-1.5 py-[1px] text-[10px] font-semibold text-white shadow">
|
||||
<span className="rounded-sm bg-emerald-600 px-1.5 py-px text-[10px] font-semibold text-white shadow-sm">
|
||||
{dragLabel} üstüne
|
||||
</span>
|
||||
<span className="h-[3px] flex-1 rounded bg-emerald-500" />
|
||||
<span className="h-[3px] flex-1 rounded-sm bg-emerald-500" />
|
||||
</div>
|
||||
)}
|
||||
{dropHint === 'after' && (
|
||||
<div className="pointer-events-none absolute inset-x-0 -bottom-1 z-30 flex items-center gap-1">
|
||||
<span className="rounded bg-emerald-600 px-1.5 py-[1px] text-[10px] font-semibold text-white shadow">
|
||||
<span className="rounded-sm bg-emerald-600 px-1.5 py-px text-[10px] font-semibold text-white shadow-sm">
|
||||
{dragLabel} altına
|
||||
</span>
|
||||
<span className="h-[3px] flex-1 rounded bg-emerald-500" />
|
||||
<span className="h-[3px] flex-1 rounded-sm bg-emerald-500" />
|
||||
</div>
|
||||
)}
|
||||
{dropHint === 'inside' && (
|
||||
<span className="pointer-events-none absolute left-1 top-1 z-30 rounded bg-emerald-600 px-1.5 py-[1px] text-[10px] font-semibold text-white shadow">
|
||||
<span className="pointer-events-none absolute left-1 top-1 z-30 rounded-sm bg-emerald-600 px-1.5 py-px text-[10px] font-semibold text-white shadow-sm">
|
||||
{node.type} içine
|
||||
</span>
|
||||
)}
|
||||
{/* Sürükleme sürerken bırakılamayan hedef açıkça söylenir. */}
|
||||
{dragging && insideDraggedSubtree && !isDragSource && (
|
||||
<span className="pointer-events-none absolute right-1 top-1 z-30 rounded bg-slate-500 px-1.5 py-[1px] text-[10px] font-semibold text-white shadow">
|
||||
<span className="pointer-events-none absolute right-1 top-1 z-30 rounded-sm bg-slate-500 px-1.5 py-px text-[10px] font-semibold text-white shadow-sm">
|
||||
{translate('::App.VisualDesignerCanvas.CannotMoveHere')}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -2158,7 +2158,7 @@ const NodeView = ({
|
|||
{interactive && (
|
||||
<span
|
||||
draggable
|
||||
className={`absolute -right-2 -top-2 z-30 h-4 w-4 cursor-grab items-center justify-center rounded-full bg-sky-600 text-[8px] text-white shadow ring-1 ring-white active:cursor-grabbing dark:ring-gray-900 ${selected ? 'flex' : 'hidden'}`}
|
||||
className={`absolute -right-2 -top-2 z-30 h-4 w-4 cursor-grab items-center justify-center rounded-full bg-sky-600 text-[8px] text-white shadow-sm ring-1 ring-white active:cursor-grabbing dark:ring-gray-900 ${selected ? 'flex' : 'hidden'}`}
|
||||
title={translate('::App.VisualDesignerCanvas.DragToMove', {
|
||||
name: node.ref || node.type,
|
||||
})}
|
||||
|
|
@ -2169,7 +2169,7 @@ const NodeView = ({
|
|||
</span>
|
||||
)}
|
||||
{interactive && refHidden && (
|
||||
<span className="absolute left-1 top-1 z-10 rounded bg-slate-700 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wider text-white">
|
||||
<span className="absolute left-1 top-1 z-10 rounded-sm bg-slate-700 px-1.5 py-0.5 text-[9px] font-semibold uppercase tracking-wider text-white">
|
||||
Gizli
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -2204,7 +2204,7 @@ const NodeView = ({
|
|||
// Form renders its own placeholder below the toolbar.
|
||||
!isFormNode(node.type) && (
|
||||
<div
|
||||
className="m-2 rounded border border-dashed border-slate-300 px-3 py-4 text-center text-xs text-slate-400"
|
||||
className="m-2 rounded-sm border border-dashed border-slate-300 px-3 py-4 text-center text-xs text-slate-400"
|
||||
{...containerDropZoneProps}
|
||||
>
|
||||
{translate('::App.VisualDesignerCanvas.DropComponentHere')}
|
||||
|
|
@ -2399,7 +2399,7 @@ const VisualCanvas = ({
|
|||
].map(([name, icon]) => (
|
||||
<button
|
||||
key={name}
|
||||
className="rounded-lg border border-slate-200 bg-white p-3 text-xs font-semibold text-slate-600 shadow-sm transition hover:border-sky-400 hover:text-sky-700 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300"
|
||||
className="rounded-lg border border-slate-200 bg-white p-3 text-xs font-semibold text-slate-600 shadow-xs transition hover:border-sky-400 hover:text-sky-700 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300"
|
||||
type="button"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
|
|
|
|||
|
|
@ -979,7 +979,7 @@ const renderNodeToCode = (
|
|||
return `${indent('<tr>', level + 1)}\n${cells}\n${indent('</tr>', level + 1)}`
|
||||
}).join('\n')
|
||||
const className = JSON.stringify(String(node.props.className || ''))
|
||||
return `${indent(`<UiKit.Table className={${className} + " [&>tbody>tr>td]:!px-1.5 [&>tbody>tr>td]:!py-1.5"} borderlessRow compact={${Boolean(node.props.compact)}} hoverable={${node.props.hoverable !== false}} overflow={${node.props.overflow !== false}} style={{ minWidth: "100%", tableLayout: "fixed", width: "100%" }}>`, level)}
|
||||
return `${indent(`<UiKit.Table className={${className} + " [&>tbody>tr>td]:px-1.5! [&>tbody>tr>td]:py-1.5!"} borderlessRow compact={${Boolean(node.props.compact)}} hoverable={${node.props.hoverable !== false}} overflow={${node.props.overflow !== false}} style={{ minWidth: "100%", tableLayout: "fixed", width: "100%" }}>`, level)}
|
||||
${indent('<tbody>', level + 1)}
|
||||
${rows}
|
||||
${indent('</tbody>', level + 1)}
|
||||
|
|
@ -1058,7 +1058,7 @@ ${indent(`if (!Array.isArray(${itemsVariable})) return <div className="rounded-l
|
|||
${indent(`const ${columnsVariable} = ${columnsExpression}`, level + 2)}
|
||||
${captionEntries.length ? `${indent(`const ${captionsVariable} = ${captionsLiteral}`, level + 2)}\n` : ''}${lookupEntries.length ? `${indent(`const ${lookupsVariable} = ${lookupsLiteral}`, level + 2)}\n` : ''}${indent(`if (!${columnsVariable}.length) return <div className="rounded-lg border border-dashed border-slate-300 bg-slate-50 p-4 text-center text-xs text-slate-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">Preview için en az bir sütun seçin.</div>`, level + 2)}
|
||||
${indent('return (', level + 2)}
|
||||
${indent(`<div className="min-w-0 ${overflowClass} rounded-lg border border-slate-200 bg-white shadow-sm dark:border-slate-700 dark:bg-slate-900" style={{ gridColumn: "1 / -1" }}>`, level + 3)}
|
||||
${indent(`<div className="min-w-0 ${overflowClass} rounded-lg border border-slate-200 bg-white shadow-xs dark:border-slate-700 dark:bg-slate-900" style={{ gridColumn: "1 / -1" }}>`, level + 3)}
|
||||
${indent(`<table className="w-full border-collapse text-left ${tableTextClass}">`, level + 4)}
|
||||
${indent('<thead className="bg-slate-100 text-slate-600 dark:bg-slate-800 dark:text-slate-200"><tr>', level + 5)}
|
||||
${indent(`{${columnsVariable}.map((column) => <th key={column} className="whitespace-nowrap border-b border-slate-200 dark:border-slate-700 ${cellSpacingClass}">{${captionEntries.length ? `${captionsVariable}[column] ?? ` : ''}(column === "value" ? "Value" : column)}</th>)}`, level + 6)}
|
||||
|
|
@ -1091,7 +1091,7 @@ ${indent('})()}', level + 1)}`
|
|||
.map((child) => nodeToCode(child, level + 4, repeatedItemVariable, formScope))
|
||||
.join('\n')
|
||||
: indent(
|
||||
`<pre className="min-w-0 overflow-auto rounded-lg border border-slate-200 bg-white p-3 text-xs text-slate-800 shadow-sm dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100">{typeof ${repeatedItemVariable} === "string" ? ${repeatedItemVariable} : JSON.stringify(${repeatedItemVariable}, null, 2)}</pre>`,
|
||||
`<pre className="min-w-0 overflow-auto rounded-lg border border-slate-200 bg-white p-3 text-xs text-slate-800 shadow-xs dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100">{typeof ${repeatedItemVariable} === "string" ? ${repeatedItemVariable} : JSON.stringify(${repeatedItemVariable}, null, 2)}</pre>`,
|
||||
level + 4,
|
||||
)
|
||||
// The collection is read once into a local: it is tested for three cases
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/** Liste/kart yonetim ekranlarindaki aksiyon ikonlari notr durur, rengi yalnizca hover'da gosterir. */
|
||||
export const ACTION_BUTTON_CLASS =
|
||||
'!h-8 !w-8 !rounded !p-0 text-slate-500 transition-colors dark:text-gray-400'
|
||||
'h-8! w-8! rounded-sm! p-0! text-slate-500 transition-colors dark:text-gray-400'
|
||||
|
||||
export const ACTION_BUTTON_HOVER = {
|
||||
blue: 'hover:!bg-blue-50 hover:text-blue-600 dark:hover:!bg-gray-800 dark:hover:text-blue-400',
|
||||
blue: 'hover:bg-blue-50! hover:text-blue-600 dark:hover:bg-gray-800! dark:hover:text-blue-400',
|
||||
green:
|
||||
'hover:!bg-green-50 hover:text-green-600 dark:hover:!bg-gray-800 dark:hover:text-green-400',
|
||||
red: 'hover:!bg-red-50 hover:text-red-600 dark:hover:!bg-gray-800 dark:hover:text-red-400',
|
||||
'hover:bg-green-50! hover:text-green-600 dark:hover:bg-gray-800! dark:hover:text-green-400',
|
||||
red: 'hover:bg-red-50! hover:text-red-600 dark:hover:bg-gray-800! dark:hover:text-red-400',
|
||||
slate:
|
||||
'hover:!bg-slate-100 hover:text-slate-700 dark:hover:!bg-gray-800 dark:hover:text-gray-200',
|
||||
'hover:bg-slate-100! hover:text-slate-700 dark:hover:bg-gray-800! dark:hover:text-gray-200',
|
||||
} as const
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -139,5 +139,4 @@ export abstract class UiEvalService {
|
|||
}
|
||||
}
|
||||
|
||||
const _global = (window || global) as any
|
||||
_global.UiEvalService = UiEvalService
|
||||
;(globalThis as any).UiEvalService = UiEvalService
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ function useAuth() {
|
|||
access_token: token,
|
||||
refresh_token: refreshToken,
|
||||
expires_in: expiresIn,
|
||||
} = resp?.data as any
|
||||
} = resp.data as any
|
||||
handleToken({ token, refreshToken, expiresIn })
|
||||
// if (resp.data.user) {
|
||||
// setUser(
|
||||
|
|
|
|||
|
|
@ -1,13 +1,5 @@
|
|||
// src/utils/tailwind.ts
|
||||
|
||||
import colors from 'tailwindcss/colors'
|
||||
// Tailwind eski renk isimlerinden kaynaklı uyarıları engelle
|
||||
delete (colors as any).lightBlue
|
||||
delete (colors as any).warmGray
|
||||
delete (colors as any).trueGray
|
||||
delete (colors as any).coolGray
|
||||
delete (colors as any).blueGray
|
||||
|
||||
// Tailwind breakpoints (px)
|
||||
export const SCREENS = {
|
||||
xs: 576,
|
||||
|
|
@ -18,28 +10,9 @@ export const SCREENS = {
|
|||
'2xl': 1536,
|
||||
} as const
|
||||
|
||||
// Border radius (Tailwind ile uyumlu)
|
||||
export const BORDER_RADIUS = {
|
||||
none: '0px',
|
||||
xs: '0.0625rem',
|
||||
sm: '0.125rem',
|
||||
DEFAULT: '0.25rem',
|
||||
md: '0.375rem',
|
||||
lg: '0.5rem',
|
||||
xl: '0.75rem',
|
||||
'2xl': '1rem',
|
||||
'3xl': '1.5rem',
|
||||
full: '9999px',
|
||||
} as const
|
||||
|
||||
// Tailwind renk paleti + senin custom 'sozsoft' renklerin
|
||||
export const TW_COLORS = {
|
||||
...colors,
|
||||
sozsoft: {
|
||||
main: '#FF99C8',
|
||||
secondary: '#FCF6BD',
|
||||
active: '#D0F4DE',
|
||||
x: '#A9DEF9',
|
||||
y: '#E4C1F9',
|
||||
},
|
||||
} as const
|
||||
/**
|
||||
* Temanin renk degiskeni (`@theme`, src/assets/styles/tailwind/index.css). Deger koda kopyalanmaz;
|
||||
* ozel gri paleti ve `sozsoft-*` renkleri dahil, CSS ile JS ayni rengi gosterir.
|
||||
*/
|
||||
export const themeColor = (name: string, shade?: string | number) =>
|
||||
`var(--color-${shade === undefined ? name : `${name}-${shade}`})`
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue