@proveanything/smartlinks-utils-ui 0.3.12 → 0.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-TY2UIZ24.js → chunk-76Y4UTYQ.js} +14 -5
- package/dist/chunk-76Y4UTYQ.js.map +1 -0
- package/dist/{chunk-MZ6JSCXO.js → chunk-JMCV6FOW.js} +2 -2
- package/dist/{chunk-MZ6JSCXO.js.map → chunk-JMCV6FOW.js.map} +1 -1
- package/dist/chunk-LLSIDR6U.js +28 -0
- package/dist/chunk-LLSIDR6U.js.map +1 -0
- package/dist/chunk-S27GIYV7.js +3 -0
- package/dist/chunk-S27GIYV7.js.map +1 -0
- package/dist/components/AssetPicker/index.js +1 -1
- package/dist/components/ConditionsEditor/index.js +1 -1
- package/dist/components/FacetRuleEditor/index.js +2 -1
- package/dist/components/FontPicker/index.js +1 -1
- package/dist/components/IconPicker/index.js +1 -1
- package/dist/components/RecordsAdmin/index.d.ts +58 -4
- package/dist/components/RecordsAdmin/index.js +441 -64
- package/dist/components/RecordsAdmin/index.js.map +1 -1
- package/dist/index.js +3 -2
- package/dist/records-AUJWCB7Q.js +3 -0
- package/dist/{records-66QWR67J.js.map → records-AUJWCB7Q.js.map} +1 -1
- package/package.json +1 -1
- package/dist/chunk-3BLWNYM4.js +0 -28
- package/dist/chunk-3BLWNYM4.js.map +0 -1
- package/dist/chunk-TY2UIZ24.js.map +0 -1
- package/dist/records-66QWR67J.js +0 -3
|
@@ -70,17 +70,26 @@ var getRecordByRef = async (ctx, ref) => {
|
|
|
70
70
|
};
|
|
71
71
|
var upsertRecord = async (ctx, write) => {
|
|
72
72
|
const ref = write.ref ?? deriveRefFromScope(write.scope);
|
|
73
|
-
const
|
|
73
|
+
const payload = {
|
|
74
74
|
ref,
|
|
75
75
|
...ctx.recordType ? { recordType: ctx.recordType } : {},
|
|
76
|
-
scope: write.scope,
|
|
77
76
|
data: write.data,
|
|
78
77
|
status: write.status,
|
|
79
78
|
startsAt: write.startsAt,
|
|
80
79
|
expiresAt: write.expiresAt,
|
|
81
80
|
customId: write.customId,
|
|
82
81
|
sourceSystem: write.sourceSystem
|
|
83
|
-
}
|
|
82
|
+
};
|
|
83
|
+
if (write.facetRule && write.facetRule.all && write.facetRule.all.length > 0) {
|
|
84
|
+
payload.facetRule = write.facetRule;
|
|
85
|
+
} else {
|
|
86
|
+
payload.scope = write.scope;
|
|
87
|
+
}
|
|
88
|
+
const res = await ctx.SL.app.records.upsert(
|
|
89
|
+
ctx.collectionId,
|
|
90
|
+
ctx.appId,
|
|
91
|
+
payload
|
|
92
|
+
);
|
|
84
93
|
return { record: res, isCreate: !!res?.created };
|
|
85
94
|
};
|
|
86
95
|
var upsertRecordForScope = async (ctx, scope, data, extra = {}) => upsertRecord(ctx, {
|
|
@@ -168,5 +177,5 @@ var deriveRefFromScope = (scope) => {
|
|
|
168
177
|
};
|
|
169
178
|
|
|
170
179
|
export { bulkDelete, bulkUpsert, deleteRecord, getRecordByRef, listRecords, matchRecords, parsedRefToScope, parsedRefToTarget, restoreRecord, scopesEqual, upsertRecord, upsertRecordForScope };
|
|
171
|
-
//# sourceMappingURL=chunk-
|
|
172
|
-
//# sourceMappingURL=chunk-
|
|
180
|
+
//# sourceMappingURL=chunk-76Y4UTYQ.js.map
|
|
181
|
+
//# sourceMappingURL=chunk-76Y4UTYQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/RecordsAdmin/data/scopeBridge.ts","../src/components/RecordsAdmin/data/records.ts"],"names":[],"mappings":"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","file":"chunk-76Y4UTYQ.js","sourcesContent":["// =============================================================================\r\n// scopeBridge — Convert between our UI `ParsedRef` and the SDK `RecordScope`.\r\n//\r\n// Our `ParsedRef` is a UI-friendly flat object that round-trips with the\r\n// `kind:id/kind:id` URL refs. The SDK's `RecordScope` is the structured\r\n// canonical form used for server-side specificity & `match()`. Use these\r\n// helpers at every boundary so we never write a record without `scope`.\r\n// =============================================================================\r\nimport type { RecordScope, RecordTarget } from './sdkTypes';\r\nimport type { ParsedRef } from '../types';\r\n\r\nexport const parsedRefToScope = (ref: ParsedRef): RecordScope => {\r\n const scope: RecordScope = {};\r\n if (ref.productId) scope.productId = ref.productId;\r\n if (ref.variantId) scope.variantId = ref.variantId;\r\n if (ref.batchId) scope.batchId = ref.batchId;\r\n if (ref.proofId) scope.proofId = ref.proofId;\r\n if (ref.facetId) {\r\n scope.facets = [{\r\n key: ref.facetId,\r\n valueKeys: ref.facetValue ? [ref.facetValue] : [],\r\n }];\r\n }\r\n return scope;\r\n};\r\n\r\nexport const parsedRefToTarget = (ref: ParsedRef): RecordTarget => {\r\n const target: RecordTarget = {};\r\n if (ref.productId) target.productId = ref.productId;\r\n if (ref.variantId) target.variantId = ref.variantId;\r\n if (ref.batchId) target.batchId = ref.batchId;\r\n if (ref.proofId) target.proofId = ref.proofId;\r\n if (ref.facetId && ref.facetValue) {\r\n target.facets = { [ref.facetId]: [ref.facetValue] };\r\n }\r\n return target;\r\n};\r\n\r\n/**\r\n * Compare a winning record's scope against the editing scope.\r\n * Returns true when they refer to the same node — used to decide\r\n * \"self\" vs \"inherited\" when consuming `match()` results.\r\n */\r\nexport const scopesEqual = (a: RecordScope, b: RecordScope): boolean => {\r\n if ((a.productId ?? null) !== (b.productId ?? null)) return false;\r\n if ((a.variantId ?? null) !== (b.variantId ?? null)) return false;\r\n if ((a.batchId ?? null) !== (b.batchId ?? null)) return false;\r\n if ((a.proofId ?? null) !== (b.proofId ?? null)) return false;\r\n const af = a.facets ?? [];\r\n const bf = b.facets ?? [];\r\n if (af.length !== bf.length) return false;\r\n const norm = (xs: typeof af) => xs\r\n .map((f) => `${f.key}:${[...f.valueKeys].sort().join(',')}`)\r\n .sort()\r\n .join('|');\r\n return norm(af) === norm(bf);\r\n};","// =============================================================================\r\n// Thin wrappers over SL.app.records.* — always admin: true here.\r\n//\r\n// As of `@proveanything/smartlinks` 1.9.0 the records surface ships a proper\r\n// `upsert()`, server-side `match()`, and atomic `bulkUpsert` / `bulkDelete`.\r\n// We delegate to those rather than rolling our own list+update sequences,\r\n// which were racy and ignored facet AND-of-OR semantics.\r\n// =============================================================================\r\nimport type {\r\n AppRecord, RecordScope, RecordTarget, BulkUpsertItem, BulkDeleteResult,\r\n MatchResult, FacetRule,\r\n} from './sdkTypes';\r\nimport type { ParsedRef, SmartLinksSDK } from '../types';\r\nimport { parsedRefToScope } from './scopeBridge';\r\n\r\nexport interface RecordsCtx {\r\n SL: SmartLinksSDK;\r\n collectionId: string;\r\n appId: string;\r\n /** Optional — when omitted, records are stored against the app id alone\r\n * (no type qualifier). Set this only when an app uses multiple record types\r\n * and needs to query/scope by type. */\r\n recordType?: string;\r\n}\r\n\r\n/** Shape of a single record write — uses the SDK's structured `scope`. */\r\nexport interface RecordWrite<T = unknown> {\r\n /** Logical key. The server canonicalises this from `scope` if omitted. */\r\n ref?: string;\r\n /** Structured scope; required for specificity / `match()` to work. */\r\n scope: RecordScope;\r\n data: T;\r\n visibility?: 'public' | 'owner' | 'admin';\r\n productId?: string;\r\n status?: string;\r\n startsAt?: string | null;\r\n expiresAt?: string | null;\r\n customId?: string;\r\n sourceSystem?: string;\r\n /**\r\n * Optional facet rule. When set, the record is targeted via this rule and\r\n * `scope` should be empty (the SDK enforces mutual exclusion). Used by\r\n * the rule editor / Targeting section.\r\n */\r\n facetRule?: FacetRule | null;\r\n}\r\n\r\nexport const listRecords = async (\r\n ctx: RecordsCtx,\r\n params: { ref?: string; refPrefix?: string; q?: string; limit?: number; offset?: number; sort?: string } = {},\r\n): Promise<{ data: AppRecord[]; total: number; hasMore: boolean }> => {\r\n const { limit = 100, offset, ref, refPrefix, q, sort } = params;\r\n const res = await ctx.SL.app.records.list(\r\n ctx.collectionId,\r\n ctx.appId,\r\n {\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n limit, offset, ref, refPrefix, q, sort,\r\n },\r\n true,\r\n );\r\n return {\r\n data: res?.data ?? [],\r\n total: res?.pagination?.total ?? (res?.data?.length ?? 0),\r\n hasMore: res?.pagination?.hasMore ?? false,\r\n };\r\n};\r\n\r\n/** Look up a single record by its canonical ref. */\r\nexport const getRecordByRef = async (\r\n ctx: RecordsCtx,\r\n ref: string,\r\n): Promise<AppRecord | null> => {\r\n const res = await ctx.SL.app.records.list(\r\n ctx.collectionId,\r\n ctx.appId,\r\n { ...(ctx.recordType ? { recordType: ctx.recordType } : {}), ref, limit: 1 },\r\n true,\r\n );\r\n return res?.data?.[0] ?? null;\r\n};\r\n\r\n/**\r\n * Atomic upsert via the SDK. Always sends `scope` so the server can compute\r\n * `specificity` and derive `ref` deterministically.\r\n */\r\nexport const upsertRecord = async <T,>(\r\n ctx: RecordsCtx,\r\n write: RecordWrite<T>,\r\n): Promise<{ record: AppRecord; isCreate: boolean }> => {\r\n const ref = write.ref ?? deriveRefFromScope(write.scope);\r\n const payload: Record<string, unknown> = {\r\n ref,\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n data: write.data as Record<string, unknown>,\r\n status: write.status,\r\n startsAt: write.startsAt,\r\n expiresAt: write.expiresAt,\r\n customId: write.customId,\r\n sourceSystem: write.sourceSystem,\r\n };\r\n // SDK 1.10 enforces mutual exclusion between `scope` and `facetRule`. Send\r\n // exactly one. When a rule is supplied the server resolves matches against\r\n // it; otherwise the structured scope drives specificity.\r\n if (write.facetRule && write.facetRule.all && write.facetRule.all.length > 0) {\r\n payload.facetRule = write.facetRule;\r\n } else {\r\n payload.scope = write.scope;\r\n }\r\n const res = await ctx.SL.app.records.upsert(\r\n ctx.collectionId, ctx.appId, payload as Parameters<typeof ctx.SL.app.records.upsert>[2],\r\n );\r\n return { record: res, isCreate: !!res?.created };\r\n};\r\n\r\n/**\r\n * Convenience wrapper for callers that only have a `ParsedRef` and a payload —\r\n * matches the previous (`ref`, `data`) call shape used by the editor hook.\r\n */\r\nexport const upsertRecordForScope = async <T,>(\r\n ctx: RecordsCtx,\r\n scope: ParsedRef,\r\n data: T,\r\n extra: { visibility?: 'public' | 'owner' | 'admin' } = {},\r\n) => upsertRecord<T>(ctx, {\r\n ref: scope.raw || undefined,\r\n scope: parsedRefToScope(scope),\r\n data,\r\n visibility: extra.visibility,\r\n});\r\n\r\nexport const deleteRecord = async (\r\n ctx: RecordsCtx,\r\n ref: string,\r\n): Promise<boolean> => {\r\n const existing = await getRecordByRef(ctx, ref).catch(() => null);\r\n if (!existing) return false;\r\n await ctx.SL.app.records.remove(ctx.collectionId, ctx.appId, existing.id, true);\r\n return true;\r\n};\r\n\r\n/** Restore a soft-deleted record by ID (admin only). */\r\nexport const restoreRecord = async (\r\n ctx: RecordsCtx,\r\n recordId: string,\r\n): Promise<AppRecord> => ctx.SL.app.records.restore(ctx.collectionId, ctx.appId, recordId);\r\n\r\n/**\r\n * Server-side match — single round trip that returns every record whose\r\n * `scope` is satisfied by `target`, ordered by descending `specificity`.\r\n * Replaces the per-scope N+1 chain walk we used pre-1.9.\r\n */\r\nexport const matchRecords = async (\r\n ctx: RecordsCtx,\r\n target: RecordTarget,\r\n opts: {\r\n strategy?: 'all' | 'best';\r\n at?: string;\r\n includeScheduled?: boolean;\r\n includeExpired?: boolean;\r\n limit?: number;\r\n } = {},\r\n): Promise<MatchResult> => ctx.SL.app.records.match(\r\n ctx.collectionId,\r\n ctx.appId,\r\n {\r\n target,\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n strategy: opts.strategy ?? 'all',\r\n at: opts.at,\r\n includeScheduled: opts.includeScheduled,\r\n includeExpired: opts.includeExpired,\r\n limit: opts.limit,\r\n },\r\n true,\r\n);\r\n\r\n/**\r\n * Server-side bulk upsert. Up to 500 rows per call; any leftover is chunked.\r\n * Each row is error-isolated by the server.\r\n */\r\nexport const bulkUpsert = async <T,>(\r\n ctx: RecordsCtx,\r\n entries: Array<{ ref?: string; scope: RecordScope; data: T; status?: string }>,\r\n): Promise<{ saved: number; failed: number }> => {\r\n const CHUNK = 500;\r\n let saved = 0;\r\n let failed = 0;\r\n for (let i = 0; i < entries.length; i += CHUNK) {\r\n const slice = entries.slice(i, i + CHUNK);\r\n const items: BulkUpsertItem[] = slice.map((e) => ({\r\n ref: e.ref ?? deriveRefFromScope(e.scope),\r\n ...(ctx.recordType ? { recordType: ctx.recordType } : {}),\r\n scope: e.scope,\r\n data: e.data as Record<string, unknown>,\r\n status: e.status,\r\n }));\r\n const res = await ctx.SL.app.records.bulkUpsert(ctx.collectionId, ctx.appId, items)\r\n .catch((): { saved: number; failed: number } => ({ saved: 0, failed: items.length }));\r\n saved += res.saved ?? 0;\r\n failed += res.failed ?? 0;\r\n }\r\n return { saved, failed };\r\n};\r\n\r\n/**\r\n * Server-side bulk delete. Accepts an explicit ref list (max 1000 per call,\r\n * chunked here) or a scope anchor (single call).\r\n */\r\nexport const bulkDelete = async (\r\n ctx: RecordsCtx,\r\n input: { refs: string[] } | { scope: Omit<RecordScope, 'facets'> },\r\n): Promise<{ removed: number }> => {\r\n if ('scope' in input) {\r\n const res: BulkDeleteResult = await ctx.SL.app.records.bulkDelete(\r\n ctx.collectionId, ctx.appId,\r\n { scope: input.scope, ...(ctx.recordType ? { recordType: ctx.recordType } : {}) },\r\n );\r\n return { removed: res.deleted ?? 0 };\r\n }\r\n\r\n const CHUNK = 1000;\r\n let removed = 0;\r\n for (let i = 0; i < input.refs.length; i += CHUNK) {\r\n const slice = input.refs.slice(i, i + CHUNK);\r\n const res: BulkDeleteResult = await ctx.SL.app.records.bulkDelete(\r\n ctx.collectionId, ctx.appId,\r\n { refs: slice, ...(ctx.recordType ? { recordType: ctx.recordType } : {}) },\r\n );\r\n removed += res.deleted ?? 0;\r\n }\r\n return { removed };\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal — derive a stable ref string from a structured scope. The server\r\n// re-derives this canonically on write; we send our best guess so callers\r\n// (and our own list/lookup helpers) can find the record by ref afterwards.\r\n// ---------------------------------------------------------------------------\r\nconst deriveRefFromScope = (scope: RecordScope): string => {\r\n const parts: string[] = [];\r\n if (scope.facets && scope.facets.length > 0) {\r\n // Sort for determinism.\r\n const sorted = [...scope.facets].sort((a, b) => a.key.localeCompare(b.key));\r\n for (const f of sorted) {\r\n const vals = [...f.valueKeys].sort().join(',');\r\n parts.push(vals ? `facet:${f.key}=${vals}` : `facet:${f.key}`);\r\n }\r\n }\r\n if (scope.productId) parts.push(`product:${scope.productId}`);\r\n if (scope.variantId) parts.push(`variant:${scope.variantId}`);\r\n if (scope.batchId) parts.push(`batch:${scope.batchId}`);\r\n if (scope.proofId) parts.push(`proof:${scope.proofId}`);\r\n return parts.join('/');\r\n};"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/FacetRuleEditor/FacetRuleEditor.tsx"],"names":[],"mappings":"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","file":"chunk-MZ6JSCXO.js","sourcesContent":["// =============================================================================\r\n// FacetRuleEditor — Friendly AND-of-OR rule builder for facet-targeted records.\r\n//\r\n// Model: `{ all: [{ facetKey, anyOf: [valueKey, ...] }, ...] }`.\r\n// - Each clause picks ONE facet key and one or more values (OR within).\r\n// - Multiple clauses are ANDed.\r\n// - Facet keys cannot repeat across clauses (server enforces; we hide already-\r\n// chosen keys from the picker).\r\n// - No NOTs, no nesting, no free-text — by design. This is the public-side\r\n// rule shape; richer logic belongs in `ConditionsEditor` (client-side only).\r\n//\r\n// UX notes:\r\n// - Empty state: a single inviting \"Pick a facet to start\" card.\r\n// - Each clause renders as a labelled row of value chips that toggle on click.\r\n// - Bottom bar shows live \"matches N products\" feedback when `preview` is set.\r\n// =============================================================================\r\nimport React, { useMemo } from 'react';\r\nimport { Plus, X, Trash2, Loader2, Check, AlertCircle } from 'lucide-react';\r\nimport { cn } from '../../utils/cn';\r\nimport { useFacets } from '../ConditionsEditor/useFacets';\r\nimport type { FacetRuleEditorProps, FacetRule, FacetRuleClause, FacetOption } from './types';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helpers\r\n// ---------------------------------------------------------------------------\r\nconst cloneRule = (rule: FacetRule | null): FacetRule => ({\r\n all: (rule?.all ?? []).map((c: FacetRuleClause) => ({ facetKey: c.facetKey, anyOf: [...c.anyOf] })),\r\n});\r\n\r\nconst updateClause = (\r\n rule: FacetRule | null,\r\n index: number,\r\n next: FacetRuleClause | null,\r\n): FacetRule | null => {\r\n const draft = cloneRule(rule);\r\n if (next === null) draft.all.splice(index, 1);\r\n else draft.all[index] = next;\r\n return draft.all.length === 0 ? null : draft;\r\n};\r\n\r\nconst findFacet = (facets: FacetOption[], key: string) =>\r\n facets.find((f) => f.key === key);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Single-clause editor: facet header + chip-grid of values.\r\n// ---------------------------------------------------------------------------\r\ninterface ClauseEditorProps {\r\n clause: FacetRuleClause;\r\n facet: FacetOption | undefined;\r\n onChange: (next: FacetRuleClause | null) => void;\r\n readOnly?: boolean;\r\n}\r\n\r\nconst ClauseEditor: React.FC<ClauseEditorProps> = ({ clause, facet, onChange, readOnly }) => {\r\n const selected = useMemo(() => new Set(clause.anyOf), [clause.anyOf]);\r\n const toggle = (valueKey: string) => {\r\n if (readOnly) return;\r\n const next = new Set(selected);\r\n if (next.has(valueKey)) next.delete(valueKey);\r\n else next.add(valueKey);\r\n onChange({ facetKey: clause.facetKey, anyOf: Array.from(next) });\r\n };\r\n\r\n const facetName = facet?.name ?? clause.facetKey;\r\n const values = facet?.values ?? [];\r\n\r\n return (\r\n <div className=\"rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 overflow-hidden\">\r\n {/* Header */}\r\n <div className=\"flex items-center gap-2 px-4 py-2.5 bg-gray-50 dark:bg-gray-800/50 border-b border-gray-200 dark:border-gray-700\">\r\n <div className=\"flex flex-col flex-1 min-w-0\">\r\n <span className=\"text-[11px] font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400\">\r\n Where\r\n </span>\r\n <span className=\"text-sm font-semibold text-gray-900 dark:text-gray-100 truncate\">\r\n {facetName}\r\n </span>\r\n </div>\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-0.5 rounded-full bg-gray-100 dark:bg-gray-700\">\r\n {clause.anyOf.length} selected\r\n </span>\r\n {!readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(null)}\r\n className=\"p-1.5 rounded-md text-gray-400 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n aria-label={`Remove ${facetName} clause`}\r\n >\r\n <Trash2 className=\"w-3.5 h-3.5\" />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"p-3\">\r\n {!facet ? (\r\n <div className=\"flex items-center gap-2 text-xs text-amber-600 dark:text-amber-400 px-2 py-1.5\">\r\n <AlertCircle className=\"w-3.5 h-3.5\" />\r\n <span>Facet \"{clause.facetKey}\" no longer exists in this collection.</span>\r\n </div>\r\n ) : values.length === 0 ? (\r\n <div className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1.5\">\r\n No values defined for this facet yet.\r\n </div>\r\n ) : (\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {values.map((v) => {\r\n const isSel = selected.has(v.key);\r\n return (\r\n <button\r\n key={v.key}\r\n type=\"button\"\r\n disabled={readOnly}\r\n onClick={() => toggle(v.key)}\r\n className={cn(\r\n 'inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium transition-all',\r\n 'border',\r\n isSel\r\n ? 'bg-blue-600 text-white border-blue-600 hover:bg-blue-700'\r\n : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border-gray-200 dark:border-gray-700 hover:border-blue-400 hover:text-blue-600 dark:hover:text-blue-400',\r\n readOnly && 'cursor-not-allowed opacity-60'\r\n )}\r\n aria-pressed={isSel}\r\n >\r\n {v.color && (\r\n <span\r\n className=\"inline-block w-2 h-2 rounded-full\"\r\n style={{ backgroundColor: v.color }}\r\n />\r\n )}\r\n {v.name}\r\n {isSel && <Check className=\"w-3 h-3\" />}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n )}\r\n {clause.anyOf.length > 1 && (\r\n <p className=\"mt-2 text-[11px] text-gray-500 dark:text-gray-400 px-1\">\r\n Matches when any of the selected values is present.\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// \"Add facet\" picker — lists facets not already used by another clause.\r\n// ---------------------------------------------------------------------------\r\ninterface AddFacetPickerProps {\r\n available: FacetOption[];\r\n onPick: (facetKey: string) => void;\r\n isFirst: boolean;\r\n}\r\n\r\nconst AddFacetPicker: React.FC<AddFacetPickerProps> = ({ available, onPick, isFirst }) => {\r\n const [open, setOpen] = React.useState(false);\r\n\r\n if (available.length === 0 && !isFirst) {\r\n return (\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1\">\r\n All available facets are in use.\r\n </p>\r\n );\r\n }\r\n\r\n if (isFirst) {\r\n // Empty state — friendly inviting card\r\n return (\r\n <div className=\"rounded-xl border-2 border-dashed border-gray-300 dark:border-gray-700 p-6 text-center\">\r\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-200 mb-1\">\r\n Pick a facet to target\r\n </p>\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 mb-4\">\r\n Records matching this rule will be applied to every product whose facets satisfy it.\r\n </p>\r\n <div className=\"flex flex-wrap gap-1.5 justify-center\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => onPick(f.key)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-xs font-medium bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-900/50 transition-colors\"\r\n >\r\n <Plus className=\"w-3 h-3\" />\r\n {f.name}\r\n </button>\r\n ))}\r\n {available.length === 0 && (\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\r\n No facets defined for this collection yet.\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"relative\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setOpen((o) => !o)}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors\"\r\n >\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n AND another facet\r\n </button>\r\n {open && (\r\n <>\r\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\r\n <div className=\"absolute z-50 mt-1 left-0 min-w-[200px] rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-lg overflow-hidden\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => { onPick(f.key); setOpen(false); }}\r\n className=\"w-full text-left px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors\"\r\n >\r\n {f.name}\r\n </button>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Live preview chip — wired through the optional `preview` prop.\r\n// ---------------------------------------------------------------------------\r\nconst PreviewChip: React.FC<{ preview: NonNullable<FacetRuleEditorProps['preview']> }> = ({ preview }) => {\r\n const { totalMatches, isLoading, isStale, error } = preview;\r\n\r\n if (error) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300\">\r\n <AlertCircle className=\"w-3 h-3\" />\r\n Preview failed\r\n </div>\r\n );\r\n }\r\n\r\n if (isLoading || isStale || totalMatches === null) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n Counting…\r\n </div>\r\n );\r\n }\r\n\r\n const tone = totalMatches === 0\r\n ? 'bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300'\r\n : 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300';\r\n\r\n return (\r\n <div className={cn('inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium', tone)}>\r\n <Check className=\"w-3 h-3\" />\r\n {totalMatches === 0\r\n ? 'Matches no products yet'\r\n : `Matches ${totalMatches} product${totalMatches === 1 ? '' : 's'}`}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Top-level component\r\n// ---------------------------------------------------------------------------\r\nexport const FacetRuleEditor: React.FC<FacetRuleEditorProps> = ({\r\n value, onChange,\r\n facets: providedFacets, collectionId, getFacets,\r\n preview, readOnly,\r\n onClear,\r\n title,\r\n description,\r\n className,\r\n}) => {\r\n const facets = useFacets(collectionId, providedFacets, getFacets);\r\n\r\n const usedKeys = useMemo(\r\n () => new Set((value?.all ?? []).map((c: FacetRuleClause) => c.facetKey)),\r\n [value],\r\n );\r\n const availableFacets = useMemo(\r\n () => facets.filter((f) => !usedKeys.has(f.key)),\r\n [facets, usedKeys],\r\n );\r\n\r\n const addClause = (facetKey: string) => {\r\n const next: FacetRule = cloneRule(value);\r\n next.all.push({ facetKey, anyOf: [] });\r\n onChange(next);\r\n };\r\n\r\n const updateAt = (i: number, next: FacetRuleClause | null) => {\r\n onChange(updateClause(value, i, next));\r\n };\r\n\r\n const hasClauses = (value?.all?.length ?? 0) > 0;\r\n\r\n return (\r\n <div className={cn('smartlinks-ui-facet-rule-editor space-y-3', className)}>\r\n {(title || description || (hasClauses && onClear) || preview) && (\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n {title && (\r\n <h3 className=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">{title}</h3>\r\n )}\r\n {description && (\r\n <p className=\"mt-0.5 text-xs text-gray-500 dark:text-gray-400\">{description}</p>\r\n )}\r\n </div>\r\n {preview && hasClauses && <PreviewChip preview={preview} />}\r\n {onClear && hasClauses && !readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={onClear}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs text-gray-500 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n >\r\n <X className=\"w-3 h-3\" />\r\n Remove rule\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n {!hasClauses ? (\r\n <AddFacetPicker available={facets} onPick={addClause} isFirst />\r\n ) : (\r\n <>\r\n {value!.all.map((clause: FacetRuleClause, i: number) => (\r\n <React.Fragment key={`${clause.facetKey}-${i}`}>\r\n {i > 0 && (\r\n <div className=\"flex items-center justify-center\">\r\n <span className=\"px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n AND\r\n </span>\r\n </div>\r\n )}\r\n <ClauseEditor\r\n clause={clause}\r\n facet={findFacet(facets, clause.facetKey)}\r\n onChange={(next) => updateAt(i, next)}\r\n readOnly={readOnly}\r\n />\r\n </React.Fragment>\r\n ))}\r\n {!readOnly && (\r\n <div className=\"pt-1\">\r\n <AddFacetPicker\r\n available={availableFacets}\r\n onPick={addClause}\r\n isFirst={false}\r\n />\r\n </div>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n};"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/FacetRuleEditor/FacetRuleEditor.tsx"],"names":[],"mappings":"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","file":"chunk-JMCV6FOW.js","sourcesContent":["// =============================================================================\r\n// FacetRuleEditor — Friendly AND-of-OR rule builder for facet-targeted records.\r\n//\r\n// Model: `{ all: [{ facetKey, anyOf: [valueKey, ...] }, ...] }`.\r\n// - Each clause picks ONE facet key and one or more values (OR within).\r\n// - Multiple clauses are ANDed.\r\n// - Facet keys cannot repeat across clauses (server enforces; we hide already-\r\n// chosen keys from the picker).\r\n// - No NOTs, no nesting, no free-text — by design. This is the public-side\r\n// rule shape; richer logic belongs in `ConditionsEditor` (client-side only).\r\n//\r\n// UX notes:\r\n// - Empty state: a single inviting \"Pick a facet to start\" card.\r\n// - Each clause renders as a labelled row of value chips that toggle on click.\r\n// - Bottom bar shows live \"matches N products\" feedback when `preview` is set.\r\n// =============================================================================\r\nimport React, { useMemo } from 'react';\r\nimport { Plus, X, Trash2, Loader2, Check, AlertCircle } from 'lucide-react';\r\nimport { cn } from '../../utils/cn';\r\nimport { useFacets } from '../ConditionsEditor/useFacets';\r\nimport type { FacetRuleEditorProps, FacetRule, FacetRuleClause, FacetOption } from './types';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Helpers\r\n// ---------------------------------------------------------------------------\r\nconst cloneRule = (rule: FacetRule | null): FacetRule => ({\r\n all: (rule?.all ?? []).map((c: FacetRuleClause) => ({ facetKey: c.facetKey, anyOf: [...c.anyOf] })),\r\n});\r\n\r\nconst updateClause = (\r\n rule: FacetRule | null,\r\n index: number,\r\n next: FacetRuleClause | null,\r\n): FacetRule | null => {\r\n const draft = cloneRule(rule);\r\n if (next === null) draft.all.splice(index, 1);\r\n else draft.all[index] = next;\r\n return draft.all.length === 0 ? null : draft;\r\n};\r\n\r\nconst findFacet = (facets: FacetOption[], key: string) =>\r\n facets.find((f) => f.key === key);\r\n\r\n// ---------------------------------------------------------------------------\r\n// Single-clause editor: facet header + chip-grid of values.\r\n// ---------------------------------------------------------------------------\r\ninterface ClauseEditorProps {\r\n clause: FacetRuleClause;\r\n facet: FacetOption | undefined;\r\n onChange: (next: FacetRuleClause | null) => void;\r\n readOnly?: boolean;\r\n}\r\n\r\nconst ClauseEditor: React.FC<ClauseEditorProps> = ({ clause, facet, onChange, readOnly }) => {\r\n const selected = useMemo(() => new Set(clause.anyOf), [clause.anyOf]);\r\n const toggle = (valueKey: string) => {\r\n if (readOnly) return;\r\n const next = new Set(selected);\r\n if (next.has(valueKey)) next.delete(valueKey);\r\n else next.add(valueKey);\r\n onChange({ facetKey: clause.facetKey, anyOf: Array.from(next) });\r\n };\r\n\r\n const facetName = facet?.name ?? clause.facetKey;\r\n const values = facet?.values ?? [];\r\n\r\n return (\r\n <div className=\"rounded-xl border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 overflow-hidden\">\r\n {/* Header */}\r\n <div className=\"flex items-center gap-2 px-4 py-2.5 bg-gray-50 dark:bg-gray-800/50 border-b border-gray-200 dark:border-gray-700\">\r\n <div className=\"flex flex-col flex-1 min-w-0\">\r\n <span className=\"text-[11px] font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400\">\r\n Where\r\n </span>\r\n <span className=\"text-sm font-semibold text-gray-900 dark:text-gray-100 truncate\">\r\n {facetName}\r\n </span>\r\n </div>\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-0.5 rounded-full bg-gray-100 dark:bg-gray-700\">\r\n {clause.anyOf.length} selected\r\n </span>\r\n {!readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={() => onChange(null)}\r\n className=\"p-1.5 rounded-md text-gray-400 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n aria-label={`Remove ${facetName} clause`}\r\n >\r\n <Trash2 className=\"w-3.5 h-3.5\" />\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"p-3\">\r\n {!facet ? (\r\n <div className=\"flex items-center gap-2 text-xs text-amber-600 dark:text-amber-400 px-2 py-1.5\">\r\n <AlertCircle className=\"w-3.5 h-3.5\" />\r\n <span>Facet \"{clause.facetKey}\" no longer exists in this collection.</span>\r\n </div>\r\n ) : values.length === 0 ? (\r\n <div className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1.5\">\r\n No values defined for this facet yet.\r\n </div>\r\n ) : (\r\n <div className=\"flex flex-wrap gap-1.5\">\r\n {values.map((v) => {\r\n const isSel = selected.has(v.key);\r\n return (\r\n <button\r\n key={v.key}\r\n type=\"button\"\r\n disabled={readOnly}\r\n onClick={() => toggle(v.key)}\r\n className={cn(\r\n 'inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium transition-all',\r\n 'border',\r\n isSel\r\n ? 'bg-blue-600 text-white border-blue-600 hover:bg-blue-700'\r\n : 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border-gray-200 dark:border-gray-700 hover:border-blue-400 hover:text-blue-600 dark:hover:text-blue-400',\r\n readOnly && 'cursor-not-allowed opacity-60'\r\n )}\r\n aria-pressed={isSel}\r\n >\r\n {v.color && (\r\n <span\r\n className=\"inline-block w-2 h-2 rounded-full\"\r\n style={{ backgroundColor: v.color }}\r\n />\r\n )}\r\n {v.name}\r\n {isSel && <Check className=\"w-3 h-3\" />}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n )}\r\n {clause.anyOf.length > 1 && (\r\n <p className=\"mt-2 text-[11px] text-gray-500 dark:text-gray-400 px-1\">\r\n Matches when any of the selected values is present.\r\n </p>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// \"Add facet\" picker — lists facets not already used by another clause.\r\n// ---------------------------------------------------------------------------\r\ninterface AddFacetPickerProps {\r\n available: FacetOption[];\r\n onPick: (facetKey: string) => void;\r\n isFirst: boolean;\r\n}\r\n\r\nconst AddFacetPicker: React.FC<AddFacetPickerProps> = ({ available, onPick, isFirst }) => {\r\n const [open, setOpen] = React.useState(false);\r\n\r\n if (available.length === 0 && !isFirst) {\r\n return (\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 px-2 py-1\">\r\n All available facets are in use.\r\n </p>\r\n );\r\n }\r\n\r\n if (isFirst) {\r\n // Empty state — friendly inviting card\r\n return (\r\n <div className=\"rounded-xl border-2 border-dashed border-gray-300 dark:border-gray-700 p-6 text-center\">\r\n <p className=\"text-sm font-medium text-gray-700 dark:text-gray-200 mb-1\">\r\n Pick a facet to target\r\n </p>\r\n <p className=\"text-xs text-gray-500 dark:text-gray-400 mb-4\">\r\n Records matching this rule will be applied to every product whose facets satisfy it.\r\n </p>\r\n <div className=\"flex flex-wrap gap-1.5 justify-center\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => onPick(f.key)}\r\n className=\"inline-flex items-center gap-1 px-3 py-1.5 rounded-full text-xs font-medium bg-blue-50 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 hover:bg-blue-100 dark:hover:bg-blue-900/50 transition-colors\"\r\n >\r\n <Plus className=\"w-3 h-3\" />\r\n {f.name}\r\n </button>\r\n ))}\r\n {available.length === 0 && (\r\n <span className=\"text-xs text-gray-500 dark:text-gray-400\">\r\n No facets defined for this collection yet.\r\n </span>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"relative\">\r\n <button\r\n type=\"button\"\r\n onClick={() => setOpen((o) => !o)}\r\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors\"\r\n >\r\n <Plus className=\"w-3.5 h-3.5\" />\r\n AND another facet\r\n </button>\r\n {open && (\r\n <>\r\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\r\n <div className=\"absolute z-50 mt-1 left-0 min-w-[200px] rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900 shadow-lg overflow-hidden\">\r\n {available.map((f) => (\r\n <button\r\n key={f.key}\r\n type=\"button\"\r\n onClick={() => { onPick(f.key); setOpen(false); }}\r\n className=\"w-full text-left px-3 py-2 text-sm text-gray-700 dark:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors\"\r\n >\r\n {f.name}\r\n </button>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Live preview chip — wired through the optional `preview` prop.\r\n// ---------------------------------------------------------------------------\r\nconst PreviewChip: React.FC<{ preview: NonNullable<FacetRuleEditorProps['preview']> }> = ({ preview }) => {\r\n const { totalMatches, isLoading, isStale, error } = preview;\r\n\r\n if (error) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-red-50 dark:bg-red-900/30 text-red-700 dark:text-red-300\">\r\n <AlertCircle className=\"w-3 h-3\" />\r\n Preview failed\r\n </div>\r\n );\r\n }\r\n\r\n if (isLoading || isStale || totalMatches === null) {\r\n return (\r\n <div className=\"inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n <Loader2 className=\"w-3 h-3 animate-spin\" />\r\n Counting…\r\n </div>\r\n );\r\n }\r\n\r\n const tone = totalMatches === 0\r\n ? 'bg-amber-50 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300'\r\n : 'bg-emerald-50 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300';\r\n\r\n return (\r\n <div className={cn('inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium', tone)}>\r\n <Check className=\"w-3 h-3\" />\r\n {totalMatches === 0\r\n ? 'Matches no products yet'\r\n : `Matches ${totalMatches} product${totalMatches === 1 ? '' : 's'}`}\r\n </div>\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Top-level component\r\n// ---------------------------------------------------------------------------\r\nexport const FacetRuleEditor: React.FC<FacetRuleEditorProps> = ({\r\n value, onChange,\r\n facets: providedFacets, collectionId, getFacets,\r\n preview, readOnly,\r\n onClear,\r\n title,\r\n description,\r\n className,\r\n}) => {\r\n const facets = useFacets(collectionId, providedFacets, getFacets);\r\n\r\n const usedKeys = useMemo(\r\n () => new Set((value?.all ?? []).map((c: FacetRuleClause) => c.facetKey)),\r\n [value],\r\n );\r\n const availableFacets = useMemo(\r\n () => facets.filter((f) => !usedKeys.has(f.key)),\r\n [facets, usedKeys],\r\n );\r\n\r\n const addClause = (facetKey: string) => {\r\n const next: FacetRule = cloneRule(value);\r\n next.all.push({ facetKey, anyOf: [] });\r\n onChange(next);\r\n };\r\n\r\n const updateAt = (i: number, next: FacetRuleClause | null) => {\r\n onChange(updateClause(value, i, next));\r\n };\r\n\r\n const hasClauses = (value?.all?.length ?? 0) > 0;\r\n\r\n return (\r\n <div className={cn('smartlinks-ui-facet-rule-editor space-y-3', className)}>\r\n {(title || description || (hasClauses && onClear) || preview) && (\r\n <div className=\"flex items-start gap-2\">\r\n <div className=\"flex-1 min-w-0\">\r\n {title && (\r\n <h3 className=\"text-sm font-semibold text-gray-900 dark:text-gray-100\">{title}</h3>\r\n )}\r\n {description && (\r\n <p className=\"mt-0.5 text-xs text-gray-500 dark:text-gray-400\">{description}</p>\r\n )}\r\n </div>\r\n {preview && hasClauses && <PreviewChip preview={preview} />}\r\n {onClear && hasClauses && !readOnly && (\r\n <button\r\n type=\"button\"\r\n onClick={onClear}\r\n className=\"inline-flex items-center gap-1 px-2 py-1 rounded-md text-xs text-gray-500 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors\"\r\n >\r\n <X className=\"w-3 h-3\" />\r\n Remove rule\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n\r\n {!hasClauses ? (\r\n <AddFacetPicker available={facets} onPick={addClause} isFirst />\r\n ) : (\r\n <>\r\n {value!.all.map((clause: FacetRuleClause, i: number) => (\r\n <React.Fragment key={`${clause.facetKey}-${i}`}>\r\n {i > 0 && (\r\n <div className=\"flex items-center justify-center\">\r\n <span className=\"px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400\">\r\n AND\r\n </span>\r\n </div>\r\n )}\r\n <ClauseEditor\r\n clause={clause}\r\n facet={findFacet(facets, clause.facetKey)}\r\n onChange={(next) => updateAt(i, next)}\r\n readOnly={readOnly}\r\n />\r\n </React.Fragment>\r\n ))}\r\n {!readOnly && (\r\n <div className=\"pt-1\">\r\n <AddFacetPicker\r\n available={availableFacets}\r\n onPick={addClause}\r\n isFirst={false}\r\n />\r\n </div>\r\n )}\r\n </>\r\n )}\r\n </div>\r\n );\r\n};"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// #style-inject:#style-inject
|
|
2
|
+
function styleInject(css, { insertAt } = {}) {
|
|
3
|
+
if (!css || typeof document === "undefined") return;
|
|
4
|
+
const head = document.head || document.getElementsByTagName("head")[0];
|
|
5
|
+
const style = document.createElement("style");
|
|
6
|
+
style.type = "text/css";
|
|
7
|
+
if (insertAt === "top") {
|
|
8
|
+
if (head.firstChild) {
|
|
9
|
+
head.insertBefore(style, head.firstChild);
|
|
10
|
+
} else {
|
|
11
|
+
head.appendChild(style);
|
|
12
|
+
}
|
|
13
|
+
} else {
|
|
14
|
+
head.appendChild(style);
|
|
15
|
+
}
|
|
16
|
+
if (style.styleSheet) {
|
|
17
|
+
style.styleSheet.cssText = css;
|
|
18
|
+
} else {
|
|
19
|
+
style.appendChild(document.createTextNode(css));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/styles.css
|
|
24
|
+
styleInject('.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n}\n.pointer-events-none {\n pointer-events: none;\n}\n.visible {\n visibility: visible;\n}\n.collapse {\n visibility: collapse;\n}\n.fixed {\n position: fixed;\n}\n.absolute {\n position: absolute;\n}\n.relative {\n position: relative;\n}\n.sticky {\n position: sticky;\n}\n.inset-0 {\n inset: 0px;\n}\n.inset-x-0 {\n left: 0px;\n right: 0px;\n}\n.bottom-0 {\n bottom: 0px;\n}\n.left-0 {\n left: 0px;\n}\n.left-1\\.5 {\n left: 0.375rem;\n}\n.left-2 {\n left: 0.5rem;\n}\n.left-2\\.5 {\n left: 0.625rem;\n}\n.left-3 {\n left: 0.75rem;\n}\n.right-0 {\n right: 0px;\n}\n.right-1\\.5 {\n right: 0.375rem;\n}\n.right-2 {\n right: 0.5rem;\n}\n.right-3 {\n right: 0.75rem;\n}\n.top-0 {\n top: 0px;\n}\n.top-0\\.5 {\n top: 0.125rem;\n}\n.top-1\\.5 {\n top: 0.375rem;\n}\n.top-1\\/2 {\n top: 50%;\n}\n.top-2 {\n top: 0.5rem;\n}\n.z-10 {\n z-index: 10;\n}\n.z-20 {\n z-index: 20;\n}\n.z-40 {\n z-index: 40;\n}\n.z-50 {\n z-index: 50;\n}\n.col-span-2 {\n grid-column: span 2 / span 2;\n}\n.mx-4 {\n margin-left: 1rem;\n margin-right: 1rem;\n}\n.mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.-mb-px {\n margin-bottom: -1px;\n}\n.mb-1 {\n margin-bottom: 0.25rem;\n}\n.mb-2 {\n margin-bottom: 0.5rem;\n}\n.mb-3 {\n margin-bottom: 0.75rem;\n}\n.mb-4 {\n margin-bottom: 1rem;\n}\n.ml-1 {\n margin-left: 0.25rem;\n}\n.ml-1\\.5 {\n margin-left: 0.375rem;\n}\n.ml-2 {\n margin-left: 0.5rem;\n}\n.ml-auto {\n margin-left: auto;\n}\n.mt-0\\.5 {\n margin-top: 0.125rem;\n}\n.mt-1 {\n margin-top: 0.25rem;\n}\n.mt-1\\.5 {\n margin-top: 0.375rem;\n}\n.mt-2 {\n margin-top: 0.5rem;\n}\n.mt-4 {\n margin-top: 1rem;\n}\n.block {\n display: block;\n}\n.inline-block {\n display: inline-block;\n}\n.inline {\n display: inline;\n}\n.flex {\n display: flex;\n}\n.inline-flex {\n display: inline-flex;\n}\n.table {\n display: table;\n}\n.grid {\n display: grid;\n}\n.contents {\n display: contents;\n}\n.hidden {\n display: none;\n}\n.aspect-square {\n aspect-ratio: 1 / 1;\n}\n.aspect-video {\n aspect-ratio: 16 / 9;\n}\n.h-1\\.5 {\n height: 0.375rem;\n}\n.h-10 {\n height: 2.5rem;\n}\n.h-11 {\n height: 2.75rem;\n}\n.h-16 {\n height: 4rem;\n}\n.h-2 {\n height: 0.5rem;\n}\n.h-2\\.5 {\n height: 0.625rem;\n}\n.h-3 {\n height: 0.75rem;\n}\n.h-3\\.5 {\n height: 0.875rem;\n}\n.h-4 {\n height: 1rem;\n}\n.h-5 {\n height: 1.25rem;\n}\n.h-6 {\n height: 1.5rem;\n}\n.h-7 {\n height: 1.75rem;\n}\n.h-8 {\n height: 2rem;\n}\n.h-9 {\n height: 2.25rem;\n}\n.h-full {\n height: 100%;\n}\n.max-h-32 {\n max-height: 8rem;\n}\n.max-h-80 {\n max-height: 20rem;\n}\n.max-h-\\[300px\\] {\n max-height: 300px;\n}\n.max-h-\\[400px\\] {\n max-height: 400px;\n}\n.max-h-\\[80vh\\] {\n max-height: 80vh;\n}\n.max-h-\\[85vh\\] {\n max-height: 85vh;\n}\n.min-h-0 {\n min-height: 0px;\n}\n.w-1\\.5 {\n width: 0.375rem;\n}\n.w-10 {\n width: 2.5rem;\n}\n.w-16 {\n width: 4rem;\n}\n.w-2 {\n width: 0.5rem;\n}\n.w-2\\.5 {\n width: 0.625rem;\n}\n.w-3 {\n width: 0.75rem;\n}\n.w-3\\.5 {\n width: 0.875rem;\n}\n.w-36 {\n width: 9rem;\n}\n.w-4 {\n width: 1rem;\n}\n.w-5 {\n width: 1.25rem;\n}\n.w-6 {\n width: 1.5rem;\n}\n.w-7 {\n width: 1.75rem;\n}\n.w-8 {\n width: 2rem;\n}\n.w-9 {\n width: 2.25rem;\n}\n.w-full {\n width: 100%;\n}\n.min-w-0 {\n min-width: 0px;\n}\n.min-w-\\[12rem\\] {\n min-width: 12rem;\n}\n.min-w-\\[200px\\] {\n min-width: 200px;\n}\n.max-w-2xl {\n max-width: 42rem;\n}\n.max-w-4xl {\n max-width: 56rem;\n}\n.max-w-\\[12rem\\] {\n max-width: 12rem;\n}\n.max-w-\\[14rem\\] {\n max-width: 14rem;\n}\n.max-w-\\[160px\\] {\n max-width: 160px;\n}\n.max-w-\\[200px\\] {\n max-width: 200px;\n}\n.max-w-full {\n max-width: 100%;\n}\n.max-w-lg {\n max-width: 32rem;\n}\n.max-w-xl {\n max-width: 36rem;\n}\n.max-w-xs {\n max-width: 20rem;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.flex-shrink-0 {\n flex-shrink: 0;\n}\n.shrink-0 {\n flex-shrink: 0;\n}\n.-translate-y-1\\/2 {\n --tw-translate-y: -50%;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.translate-x-0\\.5 {\n --tw-translate-x: 0.125rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.translate-x-4 {\n --tw-translate-x: 1rem;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.scale-110 {\n --tw-scale-x: 1.1;\n --tw-scale-y: 1.1;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n@keyframes pulse {\n 50% {\n opacity: .5;\n }\n}\n.animate-pulse {\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n}\n@keyframes spin {\n to {\n transform: rotate(360deg);\n }\n}\n.animate-spin {\n animation: spin 1s linear infinite;\n}\n.cursor-not-allowed {\n cursor: not-allowed;\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.select-none {\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n.resize-none {\n resize: none;\n}\n.appearance-none {\n -webkit-appearance: none;\n -moz-appearance: none;\n appearance: none;\n}\n.grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.grid-cols-8 {\n grid-template-columns: repeat(8, minmax(0, 1fr));\n}\n.flex-col {\n flex-direction: column;\n}\n.flex-wrap {\n flex-wrap: wrap;\n}\n.items-start {\n align-items: flex-start;\n}\n.items-end {\n align-items: flex-end;\n}\n.items-center {\n align-items: center;\n}\n.justify-end {\n justify-content: flex-end;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.gap-0\\.5 {\n gap: 0.125rem;\n}\n.gap-1 {\n gap: 0.25rem;\n}\n.gap-1\\.5 {\n gap: 0.375rem;\n}\n.gap-2 {\n gap: 0.5rem;\n}\n.gap-3 {\n gap: 0.75rem;\n}\n.space-y-0\\.5 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.125rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.125rem * var(--tw-space-y-reverse));\n}\n.space-y-1 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));\n}\n.space-y-1\\.5 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));\n}\n.space-y-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\n}\n.space-y-2\\.5 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.625rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.625rem * var(--tw-space-y-reverse));\n}\n.space-y-3 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));\n}\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.divide-y > :not([hidden]) ~ :not([hidden]) {\n --tw-divide-y-reverse: 0;\n border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\n border-bottom-width: calc(1px * var(--tw-divide-y-reverse));\n}\n.self-start {\n align-self: flex-start;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-y-auto {\n overflow-y: auto;\n}\n.truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.rounded {\n border-radius: 0.25rem;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.rounded-lg {\n border-radius: var(--radius);\n}\n.rounded-md {\n border-radius: calc(var(--radius) - 2px);\n}\n.rounded-xl {\n border-radius: 0.75rem;\n}\n.border {\n border-width: 1px;\n}\n.border-2 {\n border-width: 2px;\n}\n.border-b {\n border-bottom-width: 1px;\n}\n.border-b-2 {\n border-bottom-width: 2px;\n}\n.border-r {\n border-right-width: 1px;\n}\n.border-t {\n border-top-width: 1px;\n}\n.border-solid {\n border-style: solid;\n}\n.border-dashed {\n border-style: dashed;\n}\n.border-blue-600 {\n --tw-border-opacity: 1;\n border-color: rgb(37 99 235 / var(--tw-border-opacity, 1));\n}\n.border-border {\n border-color: hsl(var(--border));\n}\n.border-destructive {\n border-color: hsl(var(--destructive));\n}\n.border-destructive\\/50 {\n border-color: hsl(var(--destructive) / 0.5);\n}\n.border-gray-100 {\n --tw-border-opacity: 1;\n border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));\n}\n.border-gray-200 {\n --tw-border-opacity: 1;\n border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));\n}\n.border-gray-300 {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\n}\n.border-primary {\n border-color: hsl(var(--primary));\n}\n.border-primary\\/50 {\n border-color: hsl(var(--primary) / 0.5);\n}\n.border-transparent {\n border-color: transparent;\n}\n.bg-\\[hsl\\(var\\(--ra-text\\)\\)\\] {\n background-color: hsl(var(--ra-text));\n}\n.bg-accent {\n background-color: hsl(var(--accent));\n}\n.bg-amber-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(255 251 235 / var(--tw-bg-opacity, 1));\n}\n.bg-background {\n background-color: hsl(var(--background));\n}\n.bg-background\\/80 {\n background-color: hsl(var(--background) / 0.8);\n}\n.bg-black\\/50 {\n background-color: rgb(0 0 0 / 0.5);\n}\n.bg-blue-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));\n}\n.bg-blue-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));\n}\n.bg-card {\n background-color: hsl(var(--card));\n}\n.bg-destructive {\n background-color: hsl(var(--destructive));\n}\n.bg-destructive\\/10 {\n background-color: hsl(var(--destructive) / 0.1);\n}\n.bg-destructive\\/5 {\n background-color: hsl(var(--destructive) / 0.05);\n}\n.bg-destructive\\/80 {\n background-color: hsl(var(--destructive) / 0.8);\n}\n.bg-emerald-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(236 253 245 / var(--tw-bg-opacity, 1));\n}\n.bg-foreground {\n background-color: hsl(var(--foreground));\n}\n.bg-foreground\\/60 {\n background-color: hsl(var(--foreground) / 0.6);\n}\n.bg-gray-100 {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-300 {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n.bg-gray-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.bg-muted {\n background-color: hsl(var(--muted));\n}\n.bg-muted\\/20 {\n background-color: hsl(var(--muted) / 0.2);\n}\n.bg-muted\\/30 {\n background-color: hsl(var(--muted) / 0.3);\n}\n.bg-primary {\n background-color: hsl(var(--primary));\n}\n.bg-primary\\/10 {\n background-color: hsl(var(--primary) / 0.1);\n}\n.bg-primary\\/5 {\n background-color: hsl(var(--primary) / 0.05);\n}\n.bg-red-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\n}\n.bg-transparent {\n background-color: transparent;\n}\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.fill-current {\n fill: currentColor;\n}\n.object-contain {\n -o-object-fit: contain;\n object-fit: contain;\n}\n.object-cover {\n -o-object-fit: cover;\n object-fit: cover;\n}\n.p-0\\.5 {\n padding: 0.125rem;\n}\n.p-1 {\n padding: 0.25rem;\n}\n.p-1\\.5 {\n padding: 0.375rem;\n}\n.p-2 {\n padding: 0.5rem;\n}\n.p-2\\.5 {\n padding: 0.625rem;\n}\n.p-3 {\n padding: 0.75rem;\n}\n.p-4 {\n padding: 1rem;\n}\n.p-6 {\n padding: 1.5rem;\n}\n.px-1 {\n padding-left: 0.25rem;\n padding-right: 0.25rem;\n}\n.px-1\\.5 {\n padding-left: 0.375rem;\n padding-right: 0.375rem;\n}\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n.px-2\\.5 {\n padding-left: 0.625rem;\n padding-right: 0.625rem;\n}\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.px-5 {\n padding-left: 1.25rem;\n padding-right: 1.25rem;\n}\n.py-0 {\n padding-top: 0px;\n padding-bottom: 0px;\n}\n.py-0\\.5 {\n padding-top: 0.125rem;\n padding-bottom: 0.125rem;\n}\n.py-1 {\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n}\n.py-1\\.5 {\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n}\n.py-10 {\n padding-top: 2.5rem;\n padding-bottom: 2.5rem;\n}\n.py-12 {\n padding-top: 3rem;\n padding-bottom: 3rem;\n}\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.py-2\\.5 {\n padding-top: 0.625rem;\n padding-bottom: 0.625rem;\n}\n.py-3 {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n}\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.pb-1 {\n padding-bottom: 0.25rem;\n}\n.pb-2 {\n padding-bottom: 0.5rem;\n}\n.pb-3 {\n padding-bottom: 0.75rem;\n}\n.pl-1 {\n padding-left: 0.25rem;\n}\n.pl-7 {\n padding-left: 1.75rem;\n}\n.pl-8 {\n padding-left: 2rem;\n}\n.pl-9 {\n padding-left: 2.25rem;\n}\n.pr-2 {\n padding-right: 0.5rem;\n}\n.pr-3 {\n padding-right: 0.75rem;\n}\n.pr-5 {\n padding-right: 1.25rem;\n}\n.pr-9 {\n padding-right: 2.25rem;\n}\n.pt-1 {\n padding-top: 0.25rem;\n}\n.pt-2 {\n padding-top: 0.5rem;\n}\n.pt-3 {\n padding-top: 0.75rem;\n}\n.pt-4 {\n padding-top: 1rem;\n}\n.text-left {\n text-align: left;\n}\n.text-center {\n text-align: center;\n}\n.font-mono {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n "Liberation Mono",\n "Courier New",\n monospace;\n}\n.text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.text-\\[10px\\] {\n font-size: 10px;\n}\n.text-\\[11px\\] {\n font-size: 11px;\n}\n.text-\\[9px\\] {\n font-size: 9px;\n}\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.font-bold {\n font-weight: 700;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-semibold {\n font-weight: 600;\n}\n.uppercase {\n text-transform: uppercase;\n}\n.capitalize {\n text-transform: capitalize;\n}\n.\\!italic {\n font-style: italic !important;\n}\n.italic {\n font-style: italic;\n}\n.tracking-wide {\n letter-spacing: 0.025em;\n}\n.tracking-wider {\n letter-spacing: 0.05em;\n}\n.text-\\[hsl\\(var\\(--ra-surface\\)\\)\\] {\n color: hsl(var(--ra-surface));\n}\n.text-accent-foreground {\n color: hsl(var(--accent-foreground));\n}\n.text-amber-600 {\n --tw-text-opacity: 1;\n color: rgb(217 119 6 / var(--tw-text-opacity, 1));\n}\n.text-amber-700 {\n --tw-text-opacity: 1;\n color: rgb(180 83 9 / var(--tw-text-opacity, 1));\n}\n.text-background {\n color: hsl(var(--background));\n}\n.text-blue-700 {\n --tw-text-opacity: 1;\n color: rgb(29 78 216 / var(--tw-text-opacity, 1));\n}\n.text-destructive {\n color: hsl(var(--destructive));\n}\n.text-destructive-foreground {\n color: hsl(var(--destructive-foreground));\n}\n.text-emerald-700 {\n --tw-text-opacity: 1;\n color: rgb(4 120 87 / var(--tw-text-opacity, 1));\n}\n.text-foreground {\n color: hsl(var(--foreground));\n}\n.text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\n}\n.text-gray-700 {\n --tw-text-opacity: 1;\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\n}\n.text-gray-800 {\n --tw-text-opacity: 1;\n color: rgb(31 41 55 / var(--tw-text-opacity, 1));\n}\n.text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.text-muted-foreground {\n color: hsl(var(--muted-foreground));\n}\n.text-muted-foreground\\/40 {\n color: hsl(var(--muted-foreground) / 0.4);\n}\n.text-primary {\n color: hsl(var(--primary));\n}\n.text-primary-foreground {\n color: hsl(var(--primary-foreground));\n}\n.text-red-400 {\n --tw-text-opacity: 1;\n color: rgb(248 113 113 / var(--tw-text-opacity, 1));\n}\n.text-red-700 {\n --tw-text-opacity: 1;\n color: rgb(185 28 28 / var(--tw-text-opacity, 1));\n}\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.underline {\n text-decoration-line: underline;\n}\n.opacity-0 {\n opacity: 0;\n}\n.opacity-100 {\n opacity: 1;\n}\n.opacity-50 {\n opacity: 0.5;\n}\n.opacity-60 {\n opacity: 0.6;\n}\n.opacity-70 {\n opacity: 0.7;\n}\n.opacity-80 {\n opacity: 0.8;\n}\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-2xl {\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-sm {\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.shadow-xl {\n --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.outline {\n outline-style: solid;\n}\n.ring-1 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.ring-2 {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.ring-primary {\n --tw-ring-color: hsl(var(--primary)) ;\n}\n.filter {\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\n}\n.backdrop-blur-sm {\n --tw-backdrop-blur: blur(4px);\n backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);\n}\n.transition {\n transition-property:\n color,\n background-color,\n border-color,\n text-decoration-color,\n fill,\n stroke,\n opacity,\n box-shadow,\n transform,\n filter,\n backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-colors {\n transition-property:\n color,\n background-color,\n border-color,\n text-decoration-color,\n fill,\n stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-opacity {\n transition-property: opacity;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-shadow {\n transition-property: box-shadow;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-transform {\n transition-property: transform;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.duration-300 {\n transition-duration: 300ms;\n}\n.placeholder\\:text-muted-foreground::-moz-placeholder {\n color: hsl(var(--muted-foreground));\n}\n.placeholder\\:text-muted-foreground::placeholder {\n color: hsl(var(--muted-foreground));\n}\n.hover\\:border-blue-400:hover {\n --tw-border-opacity: 1;\n border-color: rgb(96 165 250 / var(--tw-border-opacity, 1));\n}\n.hover\\:border-gray-300:hover {\n --tw-border-opacity: 1;\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\n}\n.hover\\:border-muted-foreground:hover {\n border-color: hsl(var(--muted-foreground));\n}\n.hover\\:border-muted-foreground\\/40:hover {\n border-color: hsl(var(--muted-foreground) / 0.4);\n}\n.hover\\:border-ring:hover {\n border-color: hsl(var(--ring));\n}\n.hover\\:bg-\\[hsl\\(var\\(--ra-muted\\)\\)\\]:hover {\n background-color: hsl(var(--ra-muted));\n}\n.hover\\:bg-\\[hsl\\(var\\(--ra-muted\\)\\/0\\.5\\)\\]:hover {\n background-color: hsl(var(--ra-muted)/0.5);\n}\n.hover\\:bg-accent:hover {\n background-color: hsl(var(--accent));\n}\n.hover\\:bg-accent\\/30:hover {\n background-color: hsl(var(--accent) / 0.3);\n}\n.hover\\:bg-accent\\/50:hover {\n background-color: hsl(var(--accent) / 0.5);\n}\n.hover\\:bg-blue-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-blue-50\\/50:hover {\n background-color: rgb(239 246 255 / 0.5);\n}\n.hover\\:bg-blue-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-destructive:hover {\n background-color: hsl(var(--destructive));\n}\n.hover\\:bg-destructive\\/10:hover {\n background-color: hsl(var(--destructive) / 0.1);\n}\n.hover\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-50:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-muted:hover {\n background-color: hsl(var(--muted));\n}\n.hover\\:bg-primary\\/90:hover {\n background-color: hsl(var(--primary) / 0.9);\n}\n.hover\\:bg-red-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-red-50:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\n}\n.hover\\:text-accent-foreground:hover {\n color: hsl(var(--accent-foreground));\n}\n.hover\\:text-blue-500:hover {\n --tw-text-opacity: 1;\n color: rgb(59 130 246 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-blue-600:hover {\n --tw-text-opacity: 1;\n color: rgb(37 99 235 / var(--tw-text-opacity, 1));\n}\n.hover\\:text-destructive:hover {\n color: hsl(var(--destructive));\n}\n.hover\\:text-destructive\\/80:hover {\n color: hsl(var(--destructive) / 0.8);\n}\n.hover\\:text-foreground:hover {\n color: hsl(var(--foreground));\n}\n.hover\\:text-red-600:hover {\n --tw-text-opacity: 1;\n color: rgb(220 38 38 / var(--tw-text-opacity, 1));\n}\n.hover\\:underline:hover {\n text-decoration-line: underline;\n}\n.hover\\:opacity-100:hover {\n opacity: 1;\n}\n.hover\\:shadow-md:hover {\n --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.hover\\:shadow-sm:hover {\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.focus\\:outline-none:focus {\n outline: 2px solid transparent;\n outline-offset: 2px;\n}\n.focus\\:ring-1:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.focus\\:ring-2:focus {\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\n box-shadow:\n var(--tw-ring-offset-shadow),\n var(--tw-ring-shadow),\n var(--tw-shadow, 0 0 #0000);\n}\n.focus\\:ring-blue-500:focus {\n --tw-ring-opacity: 1;\n --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1)) ;\n}\n.focus\\:ring-ring:focus {\n --tw-ring-color: hsl(var(--ring)) ;\n}\n.disabled\\:cursor-not-allowed:disabled {\n cursor: not-allowed;\n}\n.disabled\\:opacity-30:disabled {\n opacity: 0.3;\n}\n.disabled\\:opacity-40:disabled {\n opacity: 0.4;\n}\n.disabled\\:opacity-50:disabled {\n opacity: 0.5;\n}\n.disabled\\:opacity-60:disabled {\n opacity: 0.6;\n}\n.disabled\\:opacity-70:disabled {\n opacity: 0.7;\n}\n.group:hover .group-hover\\:opacity-100 {\n opacity: 1;\n}\n@media (min-width: 640px) {\n .sm\\:grid-cols-10 {\n grid-template-columns: repeat(10, minmax(0, 1fr));\n }\n .sm\\:grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n }\n .sm\\:grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n}\n@media (min-width: 768px) {\n .md\\:grid-cols-12 {\n grid-template-columns: repeat(12, minmax(0, 1fr));\n }\n .md\\:grid-cols-4 {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n .md\\:grid-cols-5 {\n grid-template-columns: repeat(5, minmax(0, 1fr));\n }\n}\n@media (min-width: 1024px) {\n .lg\\:grid-cols-6 {\n grid-template-columns: repeat(6, minmax(0, 1fr));\n }\n}\n@media (prefers-color-scheme: dark) {\n .dark\\:border-gray-600 {\n --tw-border-opacity: 1;\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\n }\n .dark\\:border-gray-700 {\n --tw-border-opacity: 1;\n border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));\n }\n .dark\\:border-gray-800 {\n --tw-border-opacity: 1;\n border-color: rgb(31 41 55 / var(--tw-border-opacity, 1));\n }\n .dark\\:bg-amber-900\\/30 {\n background-color: rgb(120 53 15 / 0.3);\n }\n .dark\\:bg-blue-900\\/30 {\n background-color: rgb(30 58 138 / 0.3);\n }\n .dark\\:bg-blue-900\\/40 {\n background-color: rgb(30 58 138 / 0.4);\n }\n .dark\\:bg-emerald-900\\/30 {\n background-color: rgb(6 78 59 / 0.3);\n }\n .dark\\:bg-gray-600 {\n --tw-bg-opacity: 1;\n background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-gray-700 {\n --tw-bg-opacity: 1;\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-gray-800 {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-gray-800\\/50 {\n background-color: rgb(31 41 55 / 0.5);\n }\n .dark\\:bg-gray-900 {\n --tw-bg-opacity: 1;\n background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));\n }\n .dark\\:bg-red-900\\/30 {\n background-color: rgb(127 29 29 / 0.3);\n }\n .dark\\:text-amber-300 {\n --tw-text-opacity: 1;\n color: rgb(252 211 77 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-amber-400 {\n --tw-text-opacity: 1;\n color: rgb(251 191 36 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-blue-300 {\n --tw-text-opacity: 1;\n color: rgb(147 197 253 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-emerald-300 {\n --tw-text-opacity: 1;\n color: rgb(110 231 183 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-100 {\n --tw-text-opacity: 1;\n color: rgb(243 244 246 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-200 {\n --tw-text-opacity: 1;\n color: rgb(229 231 235 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-300 {\n --tw-text-opacity: 1;\n color: rgb(209 213 219 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n }\n .dark\\:text-red-300 {\n --tw-text-opacity: 1;\n color: rgb(252 165 165 / var(--tw-text-opacity, 1));\n }\n .dark\\:hover\\:border-blue-500:hover {\n --tw-border-opacity: 1;\n border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));\n }\n .dark\\:hover\\:border-gray-600:hover {\n --tw-border-opacity: 1;\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\n }\n .dark\\:hover\\:bg-blue-900\\/50:hover {\n background-color: rgb(30 58 138 / 0.5);\n }\n .dark\\:hover\\:bg-blue-950\\/20:hover {\n background-color: rgb(23 37 84 / 0.2);\n }\n .dark\\:hover\\:bg-gray-700:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\n }\n .dark\\:hover\\:bg-gray-800:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n }\n .dark\\:hover\\:bg-gray-800\\/50:hover {\n background-color: rgb(31 41 55 / 0.5);\n }\n .dark\\:hover\\:bg-red-900\\/20:hover {\n background-color: rgb(127 29 29 / 0.2);\n }\n .dark\\:hover\\:bg-red-900\\/30:hover {\n background-color: rgb(127 29 29 / 0.3);\n }\n .dark\\:hover\\:text-blue-400:hover {\n --tw-text-opacity: 1;\n color: rgb(96 165 250 / var(--tw-text-opacity, 1));\n }\n}\n');
|
|
25
|
+
|
|
26
|
+
export { styleInject };
|
|
27
|
+
//# sourceMappingURL=chunk-LLSIDR6U.js.map
|
|
28
|
+
//# sourceMappingURL=chunk-LLSIDR6U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["#style-inject:#style-inject","../src/styles.css"],"names":[],"mappings":";AACyB,SAAR,YAA6B,GAAA,EAAK,EAAE,QAAA,EAAS,GAAI,EAAC,EAAG;AAC1D,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,QAAA,KAAa,WAAA,EAAa;AAE7C,EAAA,MAAM,OAAO,QAAA,CAAS,IAAA,IAAQ,SAAS,oBAAA,CAAqB,MAAM,EAAE,CAAC,CAAA;AACrE,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAC5C,EAAA,KAAA,CAAM,IAAA,GAAO,UAAA;AAEb,EAAA,IAAI,aAAa,KAAA,EAAO;AACtB,IAAA,IAAI,KAAK,UAAA,EAAY;AACnB,MAAA,IAAA,CAAK,YAAA,CAAa,KAAA,EAAO,IAAA,CAAK,UAAU,CAAA;AAAA,IAC1C,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,IACxB;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,EACxB;AAEA,EAAA,IAAI,MAAM,UAAA,EAAY;AACpB,IAAA,KAAA,CAAM,WAAW,OAAA,GAAU,GAAA;AAAA,EAC7B,CAAA,MAAO;AACL,IAAA,KAAA,CAAM,WAAA,CAAY,QAAA,CAAS,cAAA,CAAe,GAAG,CAAC,CAAA;AAAA,EAChD;AACF;;;ACvB8B,WAAA,CAAY,gv9BAAov9B,CAAA","file":"chunk-LLSIDR6U.js","sourcesContent":["\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\".sr-only {\\n position: absolute;\\n width: 1px;\\n height: 1px;\\n padding: 0;\\n margin: -1px;\\n overflow: hidden;\\n clip: rect(0, 0, 0, 0);\\n white-space: nowrap;\\n border-width: 0;\\n}\\n.pointer-events-none {\\n pointer-events: none;\\n}\\n.visible {\\n visibility: visible;\\n}\\n.collapse {\\n visibility: collapse;\\n}\\n.fixed {\\n position: fixed;\\n}\\n.absolute {\\n position: absolute;\\n}\\n.relative {\\n position: relative;\\n}\\n.sticky {\\n position: sticky;\\n}\\n.inset-0 {\\n inset: 0px;\\n}\\n.inset-x-0 {\\n left: 0px;\\n right: 0px;\\n}\\n.bottom-0 {\\n bottom: 0px;\\n}\\n.left-0 {\\n left: 0px;\\n}\\n.left-1\\\\.5 {\\n left: 0.375rem;\\n}\\n.left-2 {\\n left: 0.5rem;\\n}\\n.left-2\\\\.5 {\\n left: 0.625rem;\\n}\\n.left-3 {\\n left: 0.75rem;\\n}\\n.right-0 {\\n right: 0px;\\n}\\n.right-1\\\\.5 {\\n right: 0.375rem;\\n}\\n.right-2 {\\n right: 0.5rem;\\n}\\n.right-3 {\\n right: 0.75rem;\\n}\\n.top-0 {\\n top: 0px;\\n}\\n.top-0\\\\.5 {\\n top: 0.125rem;\\n}\\n.top-1\\\\.5 {\\n top: 0.375rem;\\n}\\n.top-1\\\\/2 {\\n top: 50%;\\n}\\n.top-2 {\\n top: 0.5rem;\\n}\\n.z-10 {\\n z-index: 10;\\n}\\n.z-20 {\\n z-index: 20;\\n}\\n.z-40 {\\n z-index: 40;\\n}\\n.z-50 {\\n z-index: 50;\\n}\\n.col-span-2 {\\n grid-column: span 2 / span 2;\\n}\\n.mx-4 {\\n margin-left: 1rem;\\n margin-right: 1rem;\\n}\\n.mx-auto {\\n margin-left: auto;\\n margin-right: auto;\\n}\\n.-mb-px {\\n margin-bottom: -1px;\\n}\\n.mb-1 {\\n margin-bottom: 0.25rem;\\n}\\n.mb-2 {\\n margin-bottom: 0.5rem;\\n}\\n.mb-3 {\\n margin-bottom: 0.75rem;\\n}\\n.mb-4 {\\n margin-bottom: 1rem;\\n}\\n.ml-1 {\\n margin-left: 0.25rem;\\n}\\n.ml-1\\\\.5 {\\n margin-left: 0.375rem;\\n}\\n.ml-2 {\\n margin-left: 0.5rem;\\n}\\n.ml-auto {\\n margin-left: auto;\\n}\\n.mt-0\\\\.5 {\\n margin-top: 0.125rem;\\n}\\n.mt-1 {\\n margin-top: 0.25rem;\\n}\\n.mt-1\\\\.5 {\\n margin-top: 0.375rem;\\n}\\n.mt-2 {\\n margin-top: 0.5rem;\\n}\\n.mt-4 {\\n margin-top: 1rem;\\n}\\n.block {\\n display: block;\\n}\\n.inline-block {\\n display: inline-block;\\n}\\n.inline {\\n display: inline;\\n}\\n.flex {\\n display: flex;\\n}\\n.inline-flex {\\n display: inline-flex;\\n}\\n.table {\\n display: table;\\n}\\n.grid {\\n display: grid;\\n}\\n.contents {\\n display: contents;\\n}\\n.hidden {\\n display: none;\\n}\\n.aspect-square {\\n aspect-ratio: 1 / 1;\\n}\\n.aspect-video {\\n aspect-ratio: 16 / 9;\\n}\\n.h-1\\\\.5 {\\n height: 0.375rem;\\n}\\n.h-10 {\\n height: 2.5rem;\\n}\\n.h-11 {\\n height: 2.75rem;\\n}\\n.h-16 {\\n height: 4rem;\\n}\\n.h-2 {\\n height: 0.5rem;\\n}\\n.h-2\\\\.5 {\\n height: 0.625rem;\\n}\\n.h-3 {\\n height: 0.75rem;\\n}\\n.h-3\\\\.5 {\\n height: 0.875rem;\\n}\\n.h-4 {\\n height: 1rem;\\n}\\n.h-5 {\\n height: 1.25rem;\\n}\\n.h-6 {\\n height: 1.5rem;\\n}\\n.h-7 {\\n height: 1.75rem;\\n}\\n.h-8 {\\n height: 2rem;\\n}\\n.h-9 {\\n height: 2.25rem;\\n}\\n.h-full {\\n height: 100%;\\n}\\n.max-h-32 {\\n max-height: 8rem;\\n}\\n.max-h-80 {\\n max-height: 20rem;\\n}\\n.max-h-\\\\[300px\\\\] {\\n max-height: 300px;\\n}\\n.max-h-\\\\[400px\\\\] {\\n max-height: 400px;\\n}\\n.max-h-\\\\[80vh\\\\] {\\n max-height: 80vh;\\n}\\n.max-h-\\\\[85vh\\\\] {\\n max-height: 85vh;\\n}\\n.min-h-0 {\\n min-height: 0px;\\n}\\n.w-1\\\\.5 {\\n width: 0.375rem;\\n}\\n.w-10 {\\n width: 2.5rem;\\n}\\n.w-16 {\\n width: 4rem;\\n}\\n.w-2 {\\n width: 0.5rem;\\n}\\n.w-2\\\\.5 {\\n width: 0.625rem;\\n}\\n.w-3 {\\n width: 0.75rem;\\n}\\n.w-3\\\\.5 {\\n width: 0.875rem;\\n}\\n.w-36 {\\n width: 9rem;\\n}\\n.w-4 {\\n width: 1rem;\\n}\\n.w-5 {\\n width: 1.25rem;\\n}\\n.w-6 {\\n width: 1.5rem;\\n}\\n.w-7 {\\n width: 1.75rem;\\n}\\n.w-8 {\\n width: 2rem;\\n}\\n.w-9 {\\n width: 2.25rem;\\n}\\n.w-full {\\n width: 100%;\\n}\\n.min-w-0 {\\n min-width: 0px;\\n}\\n.min-w-\\\\[12rem\\\\] {\\n min-width: 12rem;\\n}\\n.min-w-\\\\[200px\\\\] {\\n min-width: 200px;\\n}\\n.max-w-2xl {\\n max-width: 42rem;\\n}\\n.max-w-4xl {\\n max-width: 56rem;\\n}\\n.max-w-\\\\[12rem\\\\] {\\n max-width: 12rem;\\n}\\n.max-w-\\\\[14rem\\\\] {\\n max-width: 14rem;\\n}\\n.max-w-\\\\[160px\\\\] {\\n max-width: 160px;\\n}\\n.max-w-\\\\[200px\\\\] {\\n max-width: 200px;\\n}\\n.max-w-full {\\n max-width: 100%;\\n}\\n.max-w-lg {\\n max-width: 32rem;\\n}\\n.max-w-xl {\\n max-width: 36rem;\\n}\\n.max-w-xs {\\n max-width: 20rem;\\n}\\n.flex-1 {\\n flex: 1 1 0%;\\n}\\n.flex-shrink-0 {\\n flex-shrink: 0;\\n}\\n.shrink-0 {\\n flex-shrink: 0;\\n}\\n.-translate-y-1\\\\/2 {\\n --tw-translate-y: -50%;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.translate-x-0\\\\.5 {\\n --tw-translate-x: 0.125rem;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.translate-x-4 {\\n --tw-translate-x: 1rem;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.scale-110 {\\n --tw-scale-x: 1.1;\\n --tw-scale-y: 1.1;\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n.transform {\\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\\n}\\n@keyframes pulse {\\n 50% {\\n opacity: .5;\\n }\\n}\\n.animate-pulse {\\n animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\\n}\\n@keyframes spin {\\n to {\\n transform: rotate(360deg);\\n }\\n}\\n.animate-spin {\\n animation: spin 1s linear infinite;\\n}\\n.cursor-not-allowed {\\n cursor: not-allowed;\\n}\\n.cursor-pointer {\\n cursor: pointer;\\n}\\n.select-none {\\n -webkit-user-select: none;\\n -moz-user-select: none;\\n user-select: none;\\n}\\n.resize-none {\\n resize: none;\\n}\\n.appearance-none {\\n -webkit-appearance: none;\\n -moz-appearance: none;\\n appearance: none;\\n}\\n.grid-cols-2 {\\n grid-template-columns: repeat(2, minmax(0, 1fr));\\n}\\n.grid-cols-3 {\\n grid-template-columns: repeat(3, minmax(0, 1fr));\\n}\\n.grid-cols-8 {\\n grid-template-columns: repeat(8, minmax(0, 1fr));\\n}\\n.flex-col {\\n flex-direction: column;\\n}\\n.flex-wrap {\\n flex-wrap: wrap;\\n}\\n.items-start {\\n align-items: flex-start;\\n}\\n.items-end {\\n align-items: flex-end;\\n}\\n.items-center {\\n align-items: center;\\n}\\n.justify-end {\\n justify-content: flex-end;\\n}\\n.justify-center {\\n justify-content: center;\\n}\\n.justify-between {\\n justify-content: space-between;\\n}\\n.gap-0\\\\.5 {\\n gap: 0.125rem;\\n}\\n.gap-1 {\\n gap: 0.25rem;\\n}\\n.gap-1\\\\.5 {\\n gap: 0.375rem;\\n}\\n.gap-2 {\\n gap: 0.5rem;\\n}\\n.gap-3 {\\n gap: 0.75rem;\\n}\\n.space-y-0\\\\.5 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.125rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.125rem * var(--tw-space-y-reverse));\\n}\\n.space-y-1 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.25rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.25rem * var(--tw-space-y-reverse));\\n}\\n.space-y-1\\\\.5 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));\\n}\\n.space-y-2 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\\n}\\n.space-y-2\\\\.5 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.625rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.625rem * var(--tw-space-y-reverse));\\n}\\n.space-y-3 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));\\n}\\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\\n --tw-space-y-reverse: 0;\\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\\n}\\n.divide-y > :not([hidden]) ~ :not([hidden]) {\\n --tw-divide-y-reverse: 0;\\n border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));\\n border-bottom-width: calc(1px * var(--tw-divide-y-reverse));\\n}\\n.self-start {\\n align-self: flex-start;\\n}\\n.overflow-hidden {\\n overflow: hidden;\\n}\\n.overflow-y-auto {\\n overflow-y: auto;\\n}\\n.truncate {\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.rounded {\\n border-radius: 0.25rem;\\n}\\n.rounded-full {\\n border-radius: 9999px;\\n}\\n.rounded-lg {\\n border-radius: var(--radius);\\n}\\n.rounded-md {\\n border-radius: calc(var(--radius) - 2px);\\n}\\n.rounded-xl {\\n border-radius: 0.75rem;\\n}\\n.border {\\n border-width: 1px;\\n}\\n.border-2 {\\n border-width: 2px;\\n}\\n.border-b {\\n border-bottom-width: 1px;\\n}\\n.border-b-2 {\\n border-bottom-width: 2px;\\n}\\n.border-r {\\n border-right-width: 1px;\\n}\\n.border-t {\\n border-top-width: 1px;\\n}\\n.border-solid {\\n border-style: solid;\\n}\\n.border-dashed {\\n border-style: dashed;\\n}\\n.border-blue-600 {\\n --tw-border-opacity: 1;\\n border-color: rgb(37 99 235 / var(--tw-border-opacity, 1));\\n}\\n.border-border {\\n border-color: hsl(var(--border));\\n}\\n.border-destructive {\\n border-color: hsl(var(--destructive));\\n}\\n.border-destructive\\\\/50 {\\n border-color: hsl(var(--destructive) / 0.5);\\n}\\n.border-gray-100 {\\n --tw-border-opacity: 1;\\n border-color: rgb(243 244 246 / var(--tw-border-opacity, 1));\\n}\\n.border-gray-200 {\\n --tw-border-opacity: 1;\\n border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));\\n}\\n.border-gray-300 {\\n --tw-border-opacity: 1;\\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\\n}\\n.border-primary {\\n border-color: hsl(var(--primary));\\n}\\n.border-primary\\\\/50 {\\n border-color: hsl(var(--primary) / 0.5);\\n}\\n.border-transparent {\\n border-color: transparent;\\n}\\n.bg-\\\\[hsl\\\\(var\\\\(--ra-text\\\\)\\\\)\\\\] {\\n background-color: hsl(var(--ra-text));\\n}\\n.bg-accent {\\n background-color: hsl(var(--accent));\\n}\\n.bg-amber-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(255 251 235 / var(--tw-bg-opacity, 1));\\n}\\n.bg-background {\\n background-color: hsl(var(--background));\\n}\\n.bg-background\\\\/80 {\\n background-color: hsl(var(--background) / 0.8);\\n}\\n.bg-black\\\\/50 {\\n background-color: rgb(0 0 0 / 0.5);\\n}\\n.bg-blue-100 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\\n}\\n.bg-blue-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));\\n}\\n.bg-blue-500 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1));\\n}\\n.bg-blue-600 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(37 99 235 / var(--tw-bg-opacity, 1));\\n}\\n.bg-card {\\n background-color: hsl(var(--card));\\n}\\n.bg-destructive {\\n background-color: hsl(var(--destructive));\\n}\\n.bg-destructive\\\\/10 {\\n background-color: hsl(var(--destructive) / 0.1);\\n}\\n.bg-destructive\\\\/5 {\\n background-color: hsl(var(--destructive) / 0.05);\\n}\\n.bg-destructive\\\\/80 {\\n background-color: hsl(var(--destructive) / 0.8);\\n}\\n.bg-emerald-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(236 253 245 / var(--tw-bg-opacity, 1));\\n}\\n.bg-foreground {\\n background-color: hsl(var(--foreground));\\n}\\n.bg-foreground\\\\/60 {\\n background-color: hsl(var(--foreground) / 0.6);\\n}\\n.bg-gray-100 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\\n}\\n.bg-gray-300 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\\n}\\n.bg-gray-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\\n}\\n.bg-muted {\\n background-color: hsl(var(--muted));\\n}\\n.bg-muted\\\\/20 {\\n background-color: hsl(var(--muted) / 0.2);\\n}\\n.bg-muted\\\\/30 {\\n background-color: hsl(var(--muted) / 0.3);\\n}\\n.bg-primary {\\n background-color: hsl(var(--primary));\\n}\\n.bg-primary\\\\/10 {\\n background-color: hsl(var(--primary) / 0.1);\\n}\\n.bg-primary\\\\/5 {\\n background-color: hsl(var(--primary) / 0.05);\\n}\\n.bg-red-50 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\\n}\\n.bg-transparent {\\n background-color: transparent;\\n}\\n.bg-white {\\n --tw-bg-opacity: 1;\\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\\n}\\n.fill-current {\\n fill: currentColor;\\n}\\n.object-contain {\\n -o-object-fit: contain;\\n object-fit: contain;\\n}\\n.object-cover {\\n -o-object-fit: cover;\\n object-fit: cover;\\n}\\n.p-0\\\\.5 {\\n padding: 0.125rem;\\n}\\n.p-1 {\\n padding: 0.25rem;\\n}\\n.p-1\\\\.5 {\\n padding: 0.375rem;\\n}\\n.p-2 {\\n padding: 0.5rem;\\n}\\n.p-2\\\\.5 {\\n padding: 0.625rem;\\n}\\n.p-3 {\\n padding: 0.75rem;\\n}\\n.p-4 {\\n padding: 1rem;\\n}\\n.p-6 {\\n padding: 1.5rem;\\n}\\n.px-1 {\\n padding-left: 0.25rem;\\n padding-right: 0.25rem;\\n}\\n.px-1\\\\.5 {\\n padding-left: 0.375rem;\\n padding-right: 0.375rem;\\n}\\n.px-2 {\\n padding-left: 0.5rem;\\n padding-right: 0.5rem;\\n}\\n.px-2\\\\.5 {\\n padding-left: 0.625rem;\\n padding-right: 0.625rem;\\n}\\n.px-3 {\\n padding-left: 0.75rem;\\n padding-right: 0.75rem;\\n}\\n.px-4 {\\n padding-left: 1rem;\\n padding-right: 1rem;\\n}\\n.px-5 {\\n padding-left: 1.25rem;\\n padding-right: 1.25rem;\\n}\\n.py-0 {\\n padding-top: 0px;\\n padding-bottom: 0px;\\n}\\n.py-0\\\\.5 {\\n padding-top: 0.125rem;\\n padding-bottom: 0.125rem;\\n}\\n.py-1 {\\n padding-top: 0.25rem;\\n padding-bottom: 0.25rem;\\n}\\n.py-1\\\\.5 {\\n padding-top: 0.375rem;\\n padding-bottom: 0.375rem;\\n}\\n.py-10 {\\n padding-top: 2.5rem;\\n padding-bottom: 2.5rem;\\n}\\n.py-12 {\\n padding-top: 3rem;\\n padding-bottom: 3rem;\\n}\\n.py-2 {\\n padding-top: 0.5rem;\\n padding-bottom: 0.5rem;\\n}\\n.py-2\\\\.5 {\\n padding-top: 0.625rem;\\n padding-bottom: 0.625rem;\\n}\\n.py-3 {\\n padding-top: 0.75rem;\\n padding-bottom: 0.75rem;\\n}\\n.py-4 {\\n padding-top: 1rem;\\n padding-bottom: 1rem;\\n}\\n.pb-1 {\\n padding-bottom: 0.25rem;\\n}\\n.pb-2 {\\n padding-bottom: 0.5rem;\\n}\\n.pb-3 {\\n padding-bottom: 0.75rem;\\n}\\n.pl-1 {\\n padding-left: 0.25rem;\\n}\\n.pl-7 {\\n padding-left: 1.75rem;\\n}\\n.pl-8 {\\n padding-left: 2rem;\\n}\\n.pl-9 {\\n padding-left: 2.25rem;\\n}\\n.pr-2 {\\n padding-right: 0.5rem;\\n}\\n.pr-3 {\\n padding-right: 0.75rem;\\n}\\n.pr-5 {\\n padding-right: 1.25rem;\\n}\\n.pr-9 {\\n padding-right: 2.25rem;\\n}\\n.pt-1 {\\n padding-top: 0.25rem;\\n}\\n.pt-2 {\\n padding-top: 0.5rem;\\n}\\n.pt-3 {\\n padding-top: 0.75rem;\\n}\\n.pt-4 {\\n padding-top: 1rem;\\n}\\n.text-left {\\n text-align: left;\\n}\\n.text-center {\\n text-align: center;\\n}\\n.font-mono {\\n font-family:\\n ui-monospace,\\n SFMono-Regular,\\n Menlo,\\n Monaco,\\n Consolas,\\n \\\"Liberation Mono\\\",\\n \\\"Courier New\\\",\\n monospace;\\n}\\n.text-2xl {\\n font-size: 1.5rem;\\n line-height: 2rem;\\n}\\n.text-\\\\[10px\\\\] {\\n font-size: 10px;\\n}\\n.text-\\\\[11px\\\\] {\\n font-size: 11px;\\n}\\n.text-\\\\[9px\\\\] {\\n font-size: 9px;\\n}\\n.text-base {\\n font-size: 1rem;\\n line-height: 1.5rem;\\n}\\n.text-sm {\\n font-size: 0.875rem;\\n line-height: 1.25rem;\\n}\\n.text-xs {\\n font-size: 0.75rem;\\n line-height: 1rem;\\n}\\n.font-bold {\\n font-weight: 700;\\n}\\n.font-medium {\\n font-weight: 500;\\n}\\n.font-semibold {\\n font-weight: 600;\\n}\\n.uppercase {\\n text-transform: uppercase;\\n}\\n.capitalize {\\n text-transform: capitalize;\\n}\\n.\\\\!italic {\\n font-style: italic !important;\\n}\\n.italic {\\n font-style: italic;\\n}\\n.tracking-wide {\\n letter-spacing: 0.025em;\\n}\\n.tracking-wider {\\n letter-spacing: 0.05em;\\n}\\n.text-\\\\[hsl\\\\(var\\\\(--ra-surface\\\\)\\\\)\\\\] {\\n color: hsl(var(--ra-surface));\\n}\\n.text-accent-foreground {\\n color: hsl(var(--accent-foreground));\\n}\\n.text-amber-600 {\\n --tw-text-opacity: 1;\\n color: rgb(217 119 6 / var(--tw-text-opacity, 1));\\n}\\n.text-amber-700 {\\n --tw-text-opacity: 1;\\n color: rgb(180 83 9 / var(--tw-text-opacity, 1));\\n}\\n.text-background {\\n color: hsl(var(--background));\\n}\\n.text-blue-700 {\\n --tw-text-opacity: 1;\\n color: rgb(29 78 216 / var(--tw-text-opacity, 1));\\n}\\n.text-destructive {\\n color: hsl(var(--destructive));\\n}\\n.text-destructive-foreground {\\n color: hsl(var(--destructive-foreground));\\n}\\n.text-emerald-700 {\\n --tw-text-opacity: 1;\\n color: rgb(4 120 87 / var(--tw-text-opacity, 1));\\n}\\n.text-foreground {\\n color: hsl(var(--foreground));\\n}\\n.text-gray-400 {\\n --tw-text-opacity: 1;\\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-500 {\\n --tw-text-opacity: 1;\\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-600 {\\n --tw-text-opacity: 1;\\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-700 {\\n --tw-text-opacity: 1;\\n color: rgb(55 65 81 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-800 {\\n --tw-text-opacity: 1;\\n color: rgb(31 41 55 / var(--tw-text-opacity, 1));\\n}\\n.text-gray-900 {\\n --tw-text-opacity: 1;\\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\\n}\\n.text-muted-foreground {\\n color: hsl(var(--muted-foreground));\\n}\\n.text-muted-foreground\\\\/40 {\\n color: hsl(var(--muted-foreground) / 0.4);\\n}\\n.text-primary {\\n color: hsl(var(--primary));\\n}\\n.text-primary-foreground {\\n color: hsl(var(--primary-foreground));\\n}\\n.text-red-400 {\\n --tw-text-opacity: 1;\\n color: rgb(248 113 113 / var(--tw-text-opacity, 1));\\n}\\n.text-red-700 {\\n --tw-text-opacity: 1;\\n color: rgb(185 28 28 / var(--tw-text-opacity, 1));\\n}\\n.text-white {\\n --tw-text-opacity: 1;\\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\\n}\\n.underline {\\n text-decoration-line: underline;\\n}\\n.opacity-0 {\\n opacity: 0;\\n}\\n.opacity-100 {\\n opacity: 1;\\n}\\n.opacity-50 {\\n opacity: 0.5;\\n}\\n.opacity-60 {\\n opacity: 0.6;\\n}\\n.opacity-70 {\\n opacity: 0.7;\\n}\\n.opacity-80 {\\n opacity: 0.8;\\n}\\n.shadow {\\n --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-2xl {\\n --tw-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.25);\\n --tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-lg {\\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-sm {\\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.shadow-xl {\\n --tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.outline {\\n outline-style: solid;\\n}\\n.ring-1 {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.ring-2 {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.ring-primary {\\n --tw-ring-color: hsl(var(--primary)) ;\\n}\\n.filter {\\n filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);\\n}\\n.backdrop-blur-sm {\\n --tw-backdrop-blur: blur(4px);\\n backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);\\n}\\n.transition {\\n transition-property:\\n color,\\n background-color,\\n border-color,\\n text-decoration-color,\\n fill,\\n stroke,\\n opacity,\\n box-shadow,\\n transform,\\n filter,\\n backdrop-filter;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-all {\\n transition-property: all;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-colors {\\n transition-property:\\n color,\\n background-color,\\n border-color,\\n text-decoration-color,\\n fill,\\n stroke;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-opacity {\\n transition-property: opacity;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-shadow {\\n transition-property: box-shadow;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.transition-transform {\\n transition-property: transform;\\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\\n transition-duration: 150ms;\\n}\\n.duration-300 {\\n transition-duration: 300ms;\\n}\\n.placeholder\\\\:text-muted-foreground::-moz-placeholder {\\n color: hsl(var(--muted-foreground));\\n}\\n.placeholder\\\\:text-muted-foreground::placeholder {\\n color: hsl(var(--muted-foreground));\\n}\\n.hover\\\\:border-blue-400:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(96 165 250 / var(--tw-border-opacity, 1));\\n}\\n.hover\\\\:border-gray-300:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));\\n}\\n.hover\\\\:border-muted-foreground:hover {\\n border-color: hsl(var(--muted-foreground));\\n}\\n.hover\\\\:border-muted-foreground\\\\/40:hover {\\n border-color: hsl(var(--muted-foreground) / 0.4);\\n}\\n.hover\\\\:border-ring:hover {\\n border-color: hsl(var(--ring));\\n}\\n.hover\\\\:bg-\\\\[hsl\\\\(var\\\\(--ra-muted\\\\)\\\\)\\\\]:hover {\\n background-color: hsl(var(--ra-muted));\\n}\\n.hover\\\\:bg-\\\\[hsl\\\\(var\\\\(--ra-muted\\\\)\\\\/0\\\\.5\\\\)\\\\]:hover {\\n background-color: hsl(var(--ra-muted)/0.5);\\n}\\n.hover\\\\:bg-accent:hover {\\n background-color: hsl(var(--accent));\\n}\\n.hover\\\\:bg-accent\\\\/30:hover {\\n background-color: hsl(var(--accent) / 0.3);\\n}\\n.hover\\\\:bg-accent\\\\/50:hover {\\n background-color: hsl(var(--accent) / 0.5);\\n}\\n.hover\\\\:bg-blue-100:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-blue-50\\\\/50:hover {\\n background-color: rgb(239 246 255 / 0.5);\\n}\\n.hover\\\\:bg-blue-700:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-destructive:hover {\\n background-color: hsl(var(--destructive));\\n}\\n.hover\\\\:bg-destructive\\\\/10:hover {\\n background-color: hsl(var(--destructive) / 0.1);\\n}\\n.hover\\\\:bg-gray-100:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-gray-200:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-gray-50:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-muted:hover {\\n background-color: hsl(var(--muted));\\n}\\n.hover\\\\:bg-primary\\\\/90:hover {\\n background-color: hsl(var(--primary) / 0.9);\\n}\\n.hover\\\\:bg-red-100:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(254 226 226 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:bg-red-50:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));\\n}\\n.hover\\\\:text-accent-foreground:hover {\\n color: hsl(var(--accent-foreground));\\n}\\n.hover\\\\:text-blue-500:hover {\\n --tw-text-opacity: 1;\\n color: rgb(59 130 246 / var(--tw-text-opacity, 1));\\n}\\n.hover\\\\:text-blue-600:hover {\\n --tw-text-opacity: 1;\\n color: rgb(37 99 235 / var(--tw-text-opacity, 1));\\n}\\n.hover\\\\:text-destructive:hover {\\n color: hsl(var(--destructive));\\n}\\n.hover\\\\:text-destructive\\\\/80:hover {\\n color: hsl(var(--destructive) / 0.8);\\n}\\n.hover\\\\:text-foreground:hover {\\n color: hsl(var(--foreground));\\n}\\n.hover\\\\:text-red-600:hover {\\n --tw-text-opacity: 1;\\n color: rgb(220 38 38 / var(--tw-text-opacity, 1));\\n}\\n.hover\\\\:underline:hover {\\n text-decoration-line: underline;\\n}\\n.hover\\\\:opacity-100:hover {\\n opacity: 1;\\n}\\n.hover\\\\:shadow-md:hover {\\n --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.hover\\\\:shadow-sm:hover {\\n --tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);\\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow, 0 0 #0000),\\n var(--tw-ring-shadow, 0 0 #0000),\\n var(--tw-shadow);\\n}\\n.focus\\\\:outline-none:focus {\\n outline: 2px solid transparent;\\n outline-offset: 2px;\\n}\\n.focus\\\\:ring-1:focus {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.focus\\\\:ring-2:focus {\\n --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);\\n --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);\\n box-shadow:\\n var(--tw-ring-offset-shadow),\\n var(--tw-ring-shadow),\\n var(--tw-shadow, 0 0 #0000);\\n}\\n.focus\\\\:ring-blue-500:focus {\\n --tw-ring-opacity: 1;\\n --tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1)) ;\\n}\\n.focus\\\\:ring-ring:focus {\\n --tw-ring-color: hsl(var(--ring)) ;\\n}\\n.disabled\\\\:cursor-not-allowed:disabled {\\n cursor: not-allowed;\\n}\\n.disabled\\\\:opacity-30:disabled {\\n opacity: 0.3;\\n}\\n.disabled\\\\:opacity-40:disabled {\\n opacity: 0.4;\\n}\\n.disabled\\\\:opacity-50:disabled {\\n opacity: 0.5;\\n}\\n.disabled\\\\:opacity-60:disabled {\\n opacity: 0.6;\\n}\\n.disabled\\\\:opacity-70:disabled {\\n opacity: 0.7;\\n}\\n.group:hover .group-hover\\\\:opacity-100 {\\n opacity: 1;\\n}\\n@media (min-width: 640px) {\\n .sm\\\\:grid-cols-10 {\\n grid-template-columns: repeat(10, minmax(0, 1fr));\\n }\\n .sm\\\\:grid-cols-3 {\\n grid-template-columns: repeat(3, minmax(0, 1fr));\\n }\\n .sm\\\\:grid-cols-4 {\\n grid-template-columns: repeat(4, minmax(0, 1fr));\\n }\\n}\\n@media (min-width: 768px) {\\n .md\\\\:grid-cols-12 {\\n grid-template-columns: repeat(12, minmax(0, 1fr));\\n }\\n .md\\\\:grid-cols-4 {\\n grid-template-columns: repeat(4, minmax(0, 1fr));\\n }\\n .md\\\\:grid-cols-5 {\\n grid-template-columns: repeat(5, minmax(0, 1fr));\\n }\\n}\\n@media (min-width: 1024px) {\\n .lg\\\\:grid-cols-6 {\\n grid-template-columns: repeat(6, minmax(0, 1fr));\\n }\\n}\\n@media (prefers-color-scheme: dark) {\\n .dark\\\\:border-gray-600 {\\n --tw-border-opacity: 1;\\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:border-gray-700 {\\n --tw-border-opacity: 1;\\n border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:border-gray-800 {\\n --tw-border-opacity: 1;\\n border-color: rgb(31 41 55 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:bg-amber-900\\\\/30 {\\n background-color: rgb(120 53 15 / 0.3);\\n }\\n .dark\\\\:bg-blue-900\\\\/30 {\\n background-color: rgb(30 58 138 / 0.3);\\n }\\n .dark\\\\:bg-blue-900\\\\/40 {\\n background-color: rgb(30 58 138 / 0.4);\\n }\\n .dark\\\\:bg-emerald-900\\\\/30 {\\n background-color: rgb(6 78 59 / 0.3);\\n }\\n .dark\\\\:bg-gray-600 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(75 85 99 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-gray-700 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-gray-800 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-gray-800\\\\/50 {\\n background-color: rgb(31 41 55 / 0.5);\\n }\\n .dark\\\\:bg-gray-900 {\\n --tw-bg-opacity: 1;\\n background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:bg-red-900\\\\/30 {\\n background-color: rgb(127 29 29 / 0.3);\\n }\\n .dark\\\\:text-amber-300 {\\n --tw-text-opacity: 1;\\n color: rgb(252 211 77 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-amber-400 {\\n --tw-text-opacity: 1;\\n color: rgb(251 191 36 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-blue-300 {\\n --tw-text-opacity: 1;\\n color: rgb(147 197 253 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-emerald-300 {\\n --tw-text-opacity: 1;\\n color: rgb(110 231 183 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-100 {\\n --tw-text-opacity: 1;\\n color: rgb(243 244 246 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-200 {\\n --tw-text-opacity: 1;\\n color: rgb(229 231 235 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-300 {\\n --tw-text-opacity: 1;\\n color: rgb(209 213 219 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-400 {\\n --tw-text-opacity: 1;\\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-gray-500 {\\n --tw-text-opacity: 1;\\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:text-red-300 {\\n --tw-text-opacity: 1;\\n color: rgb(252 165 165 / var(--tw-text-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:border-blue-500:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(59 130 246 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:border-gray-600:hover {\\n --tw-border-opacity: 1;\\n border-color: rgb(75 85 99 / var(--tw-border-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:bg-blue-900\\\\/50:hover {\\n background-color: rgb(30 58 138 / 0.5);\\n }\\n .dark\\\\:hover\\\\:bg-blue-950\\\\/20:hover {\\n background-color: rgb(23 37 84 / 0.2);\\n }\\n .dark\\\\:hover\\\\:bg-gray-700:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:bg-gray-800:hover {\\n --tw-bg-opacity: 1;\\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\\n }\\n .dark\\\\:hover\\\\:bg-gray-800\\\\/50:hover {\\n background-color: rgb(31 41 55 / 0.5);\\n }\\n .dark\\\\:hover\\\\:bg-red-900\\\\/20:hover {\\n background-color: rgb(127 29 29 / 0.2);\\n }\\n .dark\\\\:hover\\\\:bg-red-900\\\\/30:hover {\\n background-color: rgb(127 29 29 / 0.3);\\n }\\n .dark\\\\:hover\\\\:text-blue-400:hover {\\n --tw-text-opacity: 1;\\n color: rgb(96 165 250 / var(--tw-text-opacity, 1));\\n }\\n}\\n\")"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-S27GIYV7.js"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { CATEGORY_FALLBACKS, CATEGORY_LABELS, FontPicker, GOOGLE_FONTS_CATALOG, getGoogleFontUrl } from '../../chunk-OTJV62XV.js';
|
|
2
|
-
import '../../chunk-
|
|
2
|
+
import '../../chunk-LLSIDR6U.js';
|
|
3
3
|
import '../../chunk-L7FQ52F5.js';
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, ComponentType } from 'react';
|
|
3
|
-
import * as _proveanything_smartlinks_dist_types_appObjects from '@proveanything/smartlinks/dist/types/appObjects';
|
|
4
3
|
import { FacetRule, MatchedAt, RecordScope, AppRecord, RecordTarget, MatchResult, MatchEntry } from '@proveanything/smartlinks/dist/types/appObjects';
|
|
5
4
|
import { LucideIcon } from 'lucide-react';
|
|
6
5
|
import * as _tanstack_query_core from '@tanstack/query-core';
|
|
6
|
+
import * as _proveanything_smartlinks from '@proveanything/smartlinks';
|
|
7
7
|
import { InfiniteData } from '@tanstack/react-query';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -104,6 +104,13 @@ interface ResolvedRecord<TData = unknown> {
|
|
|
104
104
|
matchedAt?: MatchedAt;
|
|
105
105
|
/** The rule that fired. Present only when `matchedAt === 'rule'`. */
|
|
106
106
|
matchedRule?: FacetRule;
|
|
107
|
+
/**
|
|
108
|
+
* The `facetRule` attached to the winning record itself, if any. Distinct
|
|
109
|
+
* from `matchedRule` (which is set when the resolver classified the match
|
|
110
|
+
* as rule-based). For rule-targeted records (`source: 'self'` on a
|
|
111
|
+
* `rule:{id}` ref) this is the rule the editor authors against.
|
|
112
|
+
*/
|
|
113
|
+
facetRule?: FacetRule | null;
|
|
107
114
|
}
|
|
108
115
|
|
|
109
116
|
interface EditorContext<TData = unknown> {
|
|
@@ -120,10 +127,29 @@ interface EditorContext<TData = unknown> {
|
|
|
120
127
|
remove: () => Promise<void>;
|
|
121
128
|
/** True when a saved-own record exists that can be removed. */
|
|
122
129
|
canRemove: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* True when the editor's current state is structurally valid for save.
|
|
132
|
+
* Defaults to `true`; the shell flips this to `false` for rule-targeted
|
|
133
|
+
* scopes whose `facetRule` is empty / has clauses with no selected values.
|
|
134
|
+
* Save buttons should disable on `!canSave` to avoid server 500s on
|
|
135
|
+
* empty-rule upserts.
|
|
136
|
+
*/
|
|
137
|
+
canSave?: boolean;
|
|
138
|
+
/** Human-readable reason `canSave` is false (used as a tooltip). */
|
|
139
|
+
cannotSaveReason?: string;
|
|
123
140
|
/** True while an optimistic save is in flight (request not yet acknowledged). */
|
|
124
141
|
isSaving?: boolean;
|
|
125
142
|
/** Last save error, if any. Cleared when the next save attempt starts. */
|
|
126
143
|
saveError?: unknown | null;
|
|
144
|
+
/**
|
|
145
|
+
* Current facet rule attached to this record, if any. Always defined for
|
|
146
|
+
* rule-targeted scopes (`scope.kind === 'rule'`) — starts as `{ all: [] }`
|
|
147
|
+
* for a freshly created rule and is updated via `onFacetRuleChange`.
|
|
148
|
+
* Mutually exclusive with the structured `scope` on save.
|
|
149
|
+
*/
|
|
150
|
+
facetRule?: FacetRule | null;
|
|
151
|
+
/** Update the in-progress facet rule. Marks the editor dirty. */
|
|
152
|
+
onFacetRuleChange?: (next: FacetRule | null) => void;
|
|
127
153
|
}
|
|
128
154
|
|
|
129
155
|
interface CsvSchemaColumn<TData> {
|
|
@@ -1044,6 +1070,13 @@ interface Props$a<T> {
|
|
|
1044
1070
|
i18n: RecordsAdminI18n;
|
|
1045
1071
|
children: ReactNode;
|
|
1046
1072
|
preview?: ReactNode;
|
|
1073
|
+
/**
|
|
1074
|
+
* Optional Targeting section rendered above `children`. The shell mounts
|
|
1075
|
+
* this for rule-targeted records (`scope.kind === 'rule'`) so admins can
|
|
1076
|
+
* author the facet rule alongside the record's data. Plain record types
|
|
1077
|
+
* leave it `undefined` and nothing renders.
|
|
1078
|
+
*/
|
|
1079
|
+
targeting?: ReactNode;
|
|
1047
1080
|
bulkActions?: React.ComponentProps<typeof BulkActionsMenu>;
|
|
1048
1081
|
/** Extra slot rendered in the footer between the danger actions and Save. */
|
|
1049
1082
|
footerExtra?: ReactNode;
|
|
@@ -1082,7 +1115,7 @@ interface Props$a<T> {
|
|
|
1082
1115
|
/** Host-provided icons rendered before save / discard / delete labels. */
|
|
1083
1116
|
actionIcons?: Partial<Record<RecordsAdminActionKey, RecordsAdminActionIcon>>;
|
|
1084
1117
|
}
|
|
1085
|
-
declare function RecordEditor<T>({ ctx, i18n, children, preview, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, clipboard, actionLabels, actionIcons, }: Props$a<T>): react_jsx_runtime.JSX.Element;
|
|
1118
|
+
declare function RecordEditor<T>({ ctx, i18n, children, preview, targeting, bulkActions, footerExtra, onBeforeDelete, headerLabel, headerSubtitle, headerMeta, clipboard, actionLabels, actionIcons, }: Props$a<T>): react_jsx_runtime.JSX.Element;
|
|
1086
1119
|
|
|
1087
1120
|
interface InheritanceCtx {
|
|
1088
1121
|
parentValue?: Record<string, unknown> | null;
|
|
@@ -1269,6 +1302,12 @@ interface RecordWrite<T = unknown> {
|
|
|
1269
1302
|
expiresAt?: string | null;
|
|
1270
1303
|
customId?: string;
|
|
1271
1304
|
sourceSystem?: string;
|
|
1305
|
+
/**
|
|
1306
|
+
* Optional facet rule. When set, the record is targeted via this rule and
|
|
1307
|
+
* `scope` should be empty (the SDK enforces mutual exclusion). Used by
|
|
1308
|
+
* the rule editor / Targeting section.
|
|
1309
|
+
*/
|
|
1310
|
+
facetRule?: FacetRule | null;
|
|
1272
1311
|
}
|
|
1273
1312
|
declare const listRecords: (ctx: RecordsCtx, params?: {
|
|
1274
1313
|
ref?: string;
|
|
@@ -1391,6 +1430,13 @@ interface UseRecordEditorArgs<T> {
|
|
|
1391
1430
|
* (used by the shell when `dirtyStrategy === 'keep'`).
|
|
1392
1431
|
*/
|
|
1393
1432
|
reseed?: 'always' | 'preserve-dirty';
|
|
1433
|
+
/**
|
|
1434
|
+
* Initial facet rule for the record. Required for rule-targeted scopes —
|
|
1435
|
+
* pass `null` (or `{ all: [] }`) for a freshly minted `rule:{id}` ref so
|
|
1436
|
+
* the Targeting section has somewhere to author into. Ignored for pinned
|
|
1437
|
+
* scopes unless the host explicitly opts a record into rule targeting.
|
|
1438
|
+
*/
|
|
1439
|
+
initialFacetRule?: FacetRule | null;
|
|
1394
1440
|
}
|
|
1395
1441
|
declare function useRecordEditor<T>(args: UseRecordEditorArgs<T>): EditorContext<T>;
|
|
1396
1442
|
|
|
@@ -1406,6 +1452,13 @@ interface UseResolvedRecordArgs {
|
|
|
1406
1452
|
facetId?: string;
|
|
1407
1453
|
facetValue?: string;
|
|
1408
1454
|
proofId?: string;
|
|
1455
|
+
/**
|
|
1456
|
+
* Optional raw ref. Required for rule-targeted records (`rule:{id}`) so the
|
|
1457
|
+
* resolver can look them up by ref instead of running an inheritance chain.
|
|
1458
|
+
* For pinned scopes this can be left empty — the structured scope ids are
|
|
1459
|
+
* sufficient.
|
|
1460
|
+
*/
|
|
1461
|
+
ref?: string;
|
|
1409
1462
|
supportedScopes?: ScopeKind[];
|
|
1410
1463
|
enabled?: boolean;
|
|
1411
1464
|
withParent?: boolean;
|
|
@@ -1417,8 +1470,9 @@ declare function useResolvedRecord<T = unknown>(args: UseResolvedRecordArgs): {
|
|
|
1417
1470
|
source: RecordSource;
|
|
1418
1471
|
sourceRef?: string;
|
|
1419
1472
|
parentValue?: T | null | undefined;
|
|
1420
|
-
matchedAt?:
|
|
1421
|
-
matchedRule?:
|
|
1473
|
+
matchedAt?: _proveanything_smartlinks.MatchedAt;
|
|
1474
|
+
matchedRule?: _proveanything_smartlinks.FacetRule;
|
|
1475
|
+
facetRule?: _proveanything_smartlinks.FacetRule | null;
|
|
1422
1476
|
};
|
|
1423
1477
|
|
|
1424
1478
|
interface UseCollectionItemsArgs {
|