@extable/core 0.3.2 → 0.3.4
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/core.css +1 -0
- package/dist/geometry.d.ts +5 -2
- package/dist/index +5328 -0
- package/dist/index.css +1 -1
- package/dist/index.js +1667 -2501
- package/dist/index.js.map +1 -1
- package/dist/index.map +1 -0
- package/dist/numberIO-CmW6eOR7.js +978 -0
- package/dist/numberIO-CmW6eOR7.js.map +1 -0
- package/dist/numberIO.d.ts +18 -0
- package/dist/selectionManager.d.ts +4 -0
- package/dist/ssr/htmlBuilder.d.ts +11 -0
- package/dist/ssr/index +338 -0
- package/dist/ssr/index.d.ts +2 -0
- package/dist/ssr/index.js +480 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/ssr/index.map +1 -0
- package/dist/ssr/nodeShims.d.ts +14 -0
- package/dist/ssr/renderer.d.ts +27 -0
- package/dist/ssr/styleSerializer.d.ts +10 -0
- package/dist/types.d.ts +19 -2
- package/package.json +10 -4
- package/src/styles.css +885 -0
- package/style.css +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index","sources":["../../src/ssr/htmlBuilder.ts","../../src/ssr/styleSerializer.ts","../../src/ssr/renderer.ts"],"sourcesContent":["export type HTMLAttributeValue = string | number | boolean | null | undefined;\n\nexport class HTMLBuilder {\n private parts: string[] = [];\n\n openTag(tag: string, attrs?: Record<string, HTMLAttributeValue>): this {\n let html = `<${tag}`;\n if (attrs) {\n for (const [key, value] of Object.entries(attrs)) {\n if (value === true) {\n html += ` ${key}`;\n } else if (value !== false && value !== null && value !== undefined) {\n html += ` ${key}=\"${escapeHtml(String(value))}\"`;\n }\n }\n }\n html += \">\";\n this.parts.push(html);\n return this;\n }\n\n closeTag(tag: string): this {\n this.parts.push(`</${tag}>`);\n return this;\n }\n\n text(content: string): this {\n this.parts.push(escapeHtml(content));\n return this;\n }\n\n html(content: string): this {\n this.parts.push(content);\n return this;\n }\n\n build(): string {\n return this.parts.join(\"\");\n }\n}\n\nexport function escapeHtml(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\\\"/g, \""\")\n .replace(/'/g, \"'\");\n}\n","export type CSSValue = string | number | null | undefined | false;\nexport type CSSStyleMap = Record<string, CSSValue>;\n\nexport function serializeStyle(style: CSSStyleMap): string {\n const parts: string[] = [];\n for (const [key, value] of Object.entries(style)) {\n if (value === null || value === undefined || value === false) continue;\n const prop = toKebabCase(key);\n parts.push(`${prop}:${String(value)};`);\n }\n return parts.join(\"\");\n}\n\nexport class CSSBuilder {\n private rules = new Map<string, CSSStyleMap>();\n\n addRule(selector: string, style: CSSStyleMap) {\n const prev = this.rules.get(selector) ?? {};\n this.rules.set(selector, { ...prev, ...style });\n }\n\n build(options?: { minify?: boolean }): string {\n const minify = options?.minify ?? false;\n const lines: string[] = [];\n for (const [selector, style] of this.rules.entries()) {\n const body = serializeStyle(style);\n if (!body) continue;\n if (minify) {\n lines.push(`${selector}{${body}}`);\n } else {\n lines.push(`${selector} { ${body} }`);\n }\n }\n return lines.join(minify ? \"\" : \"\\n\");\n }\n}\n\nfunction toKebabCase(input: string): string {\n if (input.startsWith(\"--\")) return input;\n if (input.includes(\"-\")) return input.toLowerCase();\n return input.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);\n}\n","import { DataModel } from \"../dataModel\";\nimport { columnFormatToStyle, mergeStyle } from \"../styleResolver\";\nimport type {\n ColumnSchema,\n InternalRow,\n NumberFormat,\n IntegerFormat,\n Schema,\n View,\n ViewFilterValues,\n RowObject,\n ResolvedCellStyle,\n} from \"../types\";\nimport { coerceDatePattern, formatDateLite, parseIsoDate } from \"../dateUtils\";\nimport { formatIntegerWithPrefix, formatNumberForEdit } from \"../numberIO\";\nimport { toRawValue } from \"../cellValueCodec\";\nimport { getButtonLabel, getLinkLabel, resolveButtonAction, resolveLinkAction } from \"../actionValue\";\nimport { DEFAULT_ROW_HEIGHT_PX, HEADER_HEIGHT_PX, ROW_HEADER_WIDTH_PX, getColumnWidths } from \"../geometry\";\nimport { HTMLBuilder } from \"./htmlBuilder\";\nimport { CSSBuilder, type CSSStyleMap, serializeStyle } from \"./styleSerializer\";\n\nexport type SSRView = View & {\n columnOrder?: string[];\n columnVisibility?: Record<string, boolean>;\n};\n\nexport interface SSROptions<T extends object = Record<string, unknown>> {\n data: T[] | null | undefined;\n schema: Schema<any>;\n view?: Partial<SSRView>;\n tableAttributes?: Record<string, string | number | boolean>;\n cssMode?: \"inline\" | \"external\" | \"both\";\n cssClassName?: string;\n includeDataAttributes?: boolean;\n includeAccessibilityAttributes?: boolean;\n onFormulaError?: (error: Error, row: number, col: string) => string | void;\n onValidationError?: (error: Error, row: number, col: string) => void;\n}\n\nexport interface SSRResult {\n html: string;\n css?: string;\n metadata: {\n rowCount: number;\n columnCount: number;\n hasFormulas: boolean;\n hasConditionalStyles: boolean;\n errors: Array<{ row: number; col: string; message: string }>;\n };\n}\n\nexport function renderTableHTML<T extends object = Record<string, unknown>>(\n options: SSROptions<T>,\n): SSRResult {\n const cssMode = options.cssMode ?? \"inline\";\n const cssClassName = options.cssClassName ?? \"extable\";\n const includeDataAttributes = options.includeDataAttributes ?? true;\n const includeAccessibilityAttributes = options.includeAccessibilityAttributes ?? false;\n const view = options.view ?? {};\n const data = (options.data ?? []) as RowObject[];\n\n const baseView: View = {\n hiddenColumns: view.hiddenColumns,\n filters: view.filters,\n sorts: view.sorts,\n columnDiagnostics: view.columnDiagnostics,\n userId: view.userId,\n columnWidths: view.columnWidths,\n rowHeights: view.rowHeights,\n wrapText: view.wrapText,\n };\n\n const dataModel = new DataModel(data, options.schema, baseView);\n const schema = dataModel.getSchema();\n const effectiveView = dataModel.getView();\n const rows = dataModel.listRows();\n const columns = resolveVisibleColumns(schema, view);\n const colWidths = getColumnWidths(schema, effectiveView);\n\n const html = new HTMLBuilder();\n const cssBuilder = cssMode === \"inline\" ? null : new CSSBuilder();\n const errors: Array<{ row: number; col: string; message: string }> = [];\n\n const rootSelector = `.${cssClassName.split(/\\s+/)[0] ?? \"extable\"}`;\n if (cssBuilder && cssMode !== \"inline\") {\n for (const col of columns) {\n const baseStyle = resolvedStyleToMap(columnFormatToStyle(col));\n if (Object.keys(baseStyle).length === 0) continue;\n cssBuilder.addRule(`${rootSelector} tbody td[data-col-key=\\\"${String(col.key)}\\\"]`, baseStyle);\n }\n }\n\n const totalWidth = ROW_HEADER_WIDTH_PX + colWidths.reduce((acc, w) => acc + (w ?? 0), 0);\n const tableAttrs: Record<string, string | number | boolean> = {\n class: cssClassName,\n \"data-extable-renderer\": \"html\",\n \"data-extable-ssr\": true,\n style: `width:${totalWidth}px;`,\n ...options.tableAttributes,\n };\n if (includeAccessibilityAttributes) {\n tableAttrs.role = \"grid\";\n }\n\n html.openTag(\"table\", tableAttrs);\n html.openTag(\"thead\");\n html.openTag(\"tr\", { style: `height:${HEADER_HEIGHT_PX}px;` });\n\n const rowHeaderAttrs: Record<string, string | number | boolean> = {\n class: \"extable-row-header extable-corner\",\n \"data-col-key\": \"\",\n style: `width:${ROW_HEADER_WIDTH_PX}px;`,\n };\n html.openTag(\"th\", rowHeaderAttrs).text(\"\").closeTag(\"th\");\n\n for (const col of columns) {\n const thAttrs: Record<string, string | number | boolean> = {\n \"data-col-key\": col.key,\n };\n if (includeDataAttributes) thAttrs[\"data-col-type\"] = col.type;\n const sortDir = getColumnSortDir(effectiveView, col.key);\n const hasFilter = hasActiveColumnFilter(effectiveView, col.key);\n if (sortDir) thAttrs[\"data-extable-sort-dir\"] = sortDir;\n if (hasFilter) thAttrs[\"data-extable-fs-active\"] = \"1\";\n const width = colWidths[schema.columns.findIndex((c) => c.key === col.key)] ?? col.width;\n if (width) thAttrs.style = `width:${width}px;`;\n if (includeAccessibilityAttributes) thAttrs.scope = \"col\";\n\n html.openTag(\"th\", thAttrs);\n html.openTag(\"div\", { class: \"extable-col-header\" });\n html.openTag(\"span\", { class: \"extable-col-header-text\" }).text(col.header ?? col.key);\n html.closeTag(\"span\");\n html.openTag(\"button\", {\n type: \"button\",\n class: \"extable-filter-sort-trigger\",\n \"data-extable-fs-open\": \"1\",\n \"data-extable-col-key\": col.key,\n title: \"Filter / Sort\",\n });\n html.html(sortDir ? svgArrow(sortDir) : svgFunnel());\n html.closeTag(\"button\");\n html.closeTag(\"div\");\n html.closeTag(\"th\");\n }\n\n html.closeTag(\"tr\");\n html.closeTag(\"thead\");\n html.openTag(\"tbody\");\n\n const hasFormulas = schema.columns.some((c) => Boolean(c.formula));\n const hasConditionalStyles = schema.columns.some((c) => Boolean(c.conditionalStyle)) ||\n Boolean(schema.row?.conditionalStyle);\n\n rows.forEach((row, rowIndex) => {\n const trAttrs: Record<string, string | number | boolean> = {\n \"data-row-id\": row.id,\n style: `height:${DEFAULT_ROW_HEIGHT_PX}px;`,\n };\n if (includeDataAttributes) trAttrs[\"data-row-index\"] = rowIndex;\n html.openTag(\"tr\", trAttrs);\n\n const rowHeader: Record<string, string | number | boolean> = {\n class: \"extable-row-header\",\n };\n if (includeAccessibilityAttributes) rowHeader.scope = \"row\";\n const displayIndex = dataModel.getDisplayIndex(row.id) ?? \"\";\n html.openTag(\"th\", rowHeader).text(String(displayIndex)).closeTag(\"th\");\n\n for (const col of columns) {\n renderCell({\n html,\n row,\n rowIndex,\n col,\n dataModel,\n view: effectiveView,\n includeDataAttributes,\n cssMode,\n cssBuilder,\n rootSelector,\n errors,\n onFormulaError: options.onFormulaError,\n onValidationError: options.onValidationError,\n });\n }\n\n html.closeTag(\"tr\");\n });\n\n html.closeTag(\"tbody\");\n html.closeTag(\"table\");\n\n return {\n html: html.build(),\n css: cssBuilder?.build({ minify: true }),\n metadata: {\n rowCount: rows.length,\n columnCount: columns.length,\n hasFormulas,\n hasConditionalStyles,\n errors,\n },\n };\n}\n\nfunction resolveVisibleColumns(schema: Schema, view: Partial<SSRView>): ColumnSchema[] {\n const visibility = view.columnVisibility ?? {};\n const hidden = new Set((view.hiddenColumns ?? []).map((k) => String(k)));\n const colMap = new Map<string, ColumnSchema>();\n for (const col of schema.columns) {\n colMap.set(String(col.key), col);\n }\n const ordered: ColumnSchema[] = [];\n const seen = new Set<string>();\n\n const order = (view.columnOrder ?? []).map((k) => String(k));\n for (const key of order) {\n const col = colMap.get(key);\n if (!col) continue;\n if (!isVisibleColumn(col, visibility, hidden)) continue;\n ordered.push(col);\n seen.add(key);\n }\n\n for (const col of schema.columns) {\n const key = String(col.key);\n if (seen.has(key)) continue;\n if (!isVisibleColumn(col, visibility, hidden)) continue;\n ordered.push(col);\n }\n return ordered;\n}\n\nfunction isVisibleColumn(\n col: ColumnSchema,\n visibility: Record<string, boolean>,\n hidden: Set<string>,\n): boolean {\n const key = String(col.key);\n if (visibility[key] === false) return false;\n if (visibility[key] === true) return true;\n if (hidden.has(key)) return false;\n return true;\n}\n\nfunction renderCell(options: {\n html: HTMLBuilder;\n row: InternalRow;\n rowIndex: number;\n col: ColumnSchema;\n dataModel: DataModel;\n view: View;\n includeDataAttributes: boolean;\n cssMode: \"inline\" | \"external\" | \"both\";\n cssBuilder: CSSBuilder | null;\n rootSelector: string;\n errors: Array<{ row: number; col: string; message: string }>;\n onFormulaError?: (error: Error, row: number, col: string) => string | void;\n onValidationError?: (error: Error, row: number, col: string) => void;\n}) {\n const {\n html,\n row,\n rowIndex,\n col,\n dataModel,\n view,\n includeDataAttributes,\n cssMode,\n cssBuilder,\n rootSelector,\n errors,\n onFormulaError,\n onValidationError,\n } = options;\n\n const tdClasses = [\"extable-cell\"];\n if (col.type === \"boolean\") tdClasses.push(\"extable-boolean\");\n\n const interaction = dataModel.getCellInteraction(row.id, col.key);\n if (interaction.readonly) tdClasses.push(\"extable-readonly\");\n else tdClasses.push(\"extable-editable\");\n if (interaction.muted) tdClasses.push(\"extable-readonly-muted\");\n if (interaction.disabled) tdClasses.push(\"extable-disabled\");\n\n const wrap = view.wrapText?.[col.key] ?? col.wrapText;\n tdClasses.push(wrap ? \"cell-wrap\" : \"cell-nowrap\");\n\n const align =\n col.style?.align ??\n (col.type === \"number\" || col.type === \"int\" || col.type === \"uint\" ? \"right\" : \"left\");\n tdClasses.push(align === \"right\" ? \"align-right\" : \"align-left\");\n\n const condRes = dataModel.resolveConditionalStyle(row.id, col);\n const cellStyle = dataModel.getCellStyle(row.id, col.key);\n const baseStyle = columnFormatToStyle(col);\n const withCond = condRes.delta ? mergeStyle(baseStyle, condRes.delta) : baseStyle;\n const resolved = cellStyle ? mergeStyle(withCond, cellStyle) : withCond;\n\n const marker = dataModel.getCellMarker(row.id, col.key);\n if (marker) {\n tdClasses.push(marker.level === \"warning\" ? \"extable-diag-warning\" : \"extable-diag-error\");\n }\n\n const raw = dataModel.getRawCell(row.id, col.key);\n const valueRes = dataModel.resolveCellValue(row.id, col);\n let textOverride = valueRes.textOverride ?? (condRes.forceErrorText ? \"#ERROR\" : undefined);\n\n if (valueRes.diagnostic?.source === \"formula\") {\n const err = new Error(valueRes.diagnostic.message);\n const replacement = onFormulaError?.(err, rowIndex, String(col.key));\n errors.push({ row: rowIndex, col: String(col.key), message: err.message });\n if (typeof replacement === \"string\") textOverride = replacement;\n }\n\n const validationMsg = dataModel.getCellValidationMessage(row.id, col.key);\n if (validationMsg) {\n const err = new Error(validationMsg);\n errors.push({ row: rowIndex, col: String(col.key), message: err.message });\n onValidationError?.(err, rowIndex, String(col.key));\n }\n\n const formatted = textOverride\n ? { text: textOverride }\n : formatValue(valueRes.value, col);\n const resolvedWithFormat =\n formatted.color && formatted.color !== resolved.textColor\n ? { ...resolved, textColor: formatted.color }\n : resolved;\n\n const tagValues = col.type === \"tags\" && !textOverride ? resolveTagValues(valueRes.value) : null;\n const isActionType = col.type === \"button\" || col.type === \"link\";\n const actionValue = isActionType\n ? col.type === \"button\"\n ? resolveButtonAction(valueRes.value)\n : resolveLinkAction(valueRes.value)\n : null;\n const actionLabel = isActionType\n ? col.type === \"button\"\n ? getButtonLabel(valueRes.value)\n : getLinkLabel(valueRes.value)\n : \"\";\n\n const tdAttrs: Record<string, string | number | boolean> = {\n class: tdClasses.join(\" \"),\n \"data-col-key\": col.key,\n };\n\n if (includeDataAttributes) {\n tdAttrs[\"data-row-id\"] = row.id;\n tdAttrs[\"data-col-type\"] = col.type;\n tdAttrs[\"data-cell\"] = `${rowIndex}:${String(col.key)}`;\n if (col.formula) tdAttrs[\"data-computed\"] = true;\n if (interaction.readonly) tdAttrs[\"data-readonly\"] = true;\n if (marker?.level === \"error\") tdAttrs[\"data-invalid\"] = true;\n if (marker) tdAttrs[\"data-extable-diag-message\"] = marker.message;\n } else if (marker) {\n tdAttrs[\"data-extable-diag-message\"] = marker.message;\n }\n\n const rawNumbered = toRawValue(raw, valueRes.value, col);\n if (rawNumbered !== null) {\n tdAttrs[\"data-raw\"] = rawNumbered;\n } else {\n const rawStr = raw === null || raw === undefined ? \"\" : String(raw);\n tdAttrs[\"data-raw\"] = rawStr;\n }\n\n if (cssMode === \"inline\" || cssMode === \"both\") {\n const needsInline = cssMode === \"inline\" || Boolean(condRes.delta || cellStyle || formatted.color);\n const inlineStyle = needsInline ? serializeStyle(resolvedStyleToMap(resolvedWithFormat)) : \"\";\n if (inlineStyle) tdAttrs.style = inlineStyle;\n } else if (cssMode === \"external\" && cssBuilder) {\n const selector = `${rootSelector} tbody tr[data-row-id=\\\"${row.id}\\\"] td[data-col-key=\\\"${String(col.key)}\\\"]`;\n cssBuilder.addRule(selector, resolvedStyleToMap(resolvedWithFormat));\n }\n\n html.openTag(\"td\", tdAttrs);\n\n if (tagValues && tagValues.length) {\n html.openTag(\"div\", { class: \"extable-tag-list\" });\n tagValues.forEach((tag, index) => {\n html.openTag(\"span\", { class: \"extable-tag\" });\n html.openTag(\"span\", { class: \"extable-tag-label\" }).text(tag).closeTag(\"span\");\n html.openTag(\"button\", {\n type: \"button\",\n class: \"extable-tag-remove\",\n \"data-extable-tag-remove\": \"1\",\n \"data-extable-tag-index\": String(index),\n disabled: interaction.readonly || interaction.disabled,\n });\n html.text(\"×\");\n html.closeTag(\"button\");\n html.closeTag(\"span\");\n });\n html.closeTag(\"div\");\n } else if (isActionType && !textOverride && actionValue && actionLabel) {\n const actionAttrs: Record<string, string | number | boolean> = {\n class: col.type === \"button\" ? \"extable-action-button\" : \"extable-action-link\",\n \"data-extable-action\": col.type,\n };\n if (interaction.disabled) {\n actionAttrs.class = `${actionAttrs.class} extable-action-disabled`;\n }\n if (col.type === \"button\") {\n actionAttrs.type = \"button\";\n html.openTag(\"button\", actionAttrs);\n html.text(actionLabel);\n html.closeTag(\"button\");\n } else {\n html.openTag(\"span\", actionAttrs);\n html.text(actionLabel);\n html.closeTag(\"span\");\n }\n } else {\n html.text(actionLabel || formatted.text);\n }\n\n html.closeTag(\"td\");\n}\n\nfunction formatValue(value: unknown, col: ColumnSchema): { text: string; color?: string } {\n if (value === null || value === undefined) return { text: \"\" };\n if (col.type === \"button\") {\n const label = getButtonLabel(value);\n return { text: label || String(value) };\n }\n if (col.type === \"link\") {\n const label = getLinkLabel(value);\n return { text: label || String(value) };\n }\n if (col.type === \"tags\") {\n const tags = resolveTagValues(value);\n if (tags) return { text: tags.join(\", \") };\n }\n if (col.type === \"enum\") {\n if (value && typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n if (obj.kind === \"enum\" && typeof obj.value === \"string\") {\n return { text: obj.value };\n }\n }\n }\n if (col.type === \"boolean\") {\n if (col.format === \"checkbox\" || !col.format) {\n return { text: value ? \"☑\" : \"☐\" };\n }\n if (Array.isArray(col.format) && col.format.length >= 2) {\n return { text: value ? String(col.format[0]) : String(col.format[1]) };\n }\n return { text: value ? String(col.format) : \"\" };\n }\n if (col.type === \"number\" && typeof value === \"number\") {\n const num = value;\n const fmt = col.format as NumberFormat | undefined;\n const token = fmt?.format ?? \"decimal\";\n if (token === \"scientific\") {\n const text = formatNumberForEdit(num, { format: \"scientific\", precision: fmt?.precision });\n const color = fmt?.negativeRed && num < 0 ? \"#b91c1c\" : undefined;\n return { text, color };\n }\n\n const opts: Intl.NumberFormatOptions = {};\n if (fmt?.scale !== undefined) {\n opts.minimumFractionDigits = fmt.scale;\n opts.maximumFractionDigits = fmt.scale;\n }\n opts.useGrouping = Boolean(fmt?.thousandSeparator);\n const text = new Intl.NumberFormat(\"en-US\", opts).format(num);\n const color = fmt?.negativeRed && num < 0 ? \"#b91c1c\" : undefined;\n return { text, color };\n }\n\n if ((col.type === \"int\" || col.type === \"uint\") && typeof value === \"number\") {\n const num = value;\n const fmt = col.format as IntegerFormat | undefined;\n const token = fmt?.format ?? \"decimal\";\n if (token === \"binary\" || token === \"octal\" || token === \"hex\") {\n const text = formatIntegerWithPrefix(num, token);\n const color = fmt?.negativeRed && num < 0 ? \"#b91c1c\" : undefined;\n return { text, color };\n }\n\n const opts: Intl.NumberFormatOptions = {\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n useGrouping: Boolean(fmt?.thousandSeparator),\n };\n const text = new Intl.NumberFormat(\"en-US\", opts).format(num);\n const color = fmt?.negativeRed && num < 0 ? \"#b91c1c\" : undefined;\n return { text, color };\n }\n\n if (\n (col.type === \"date\" || col.type === \"time\" || col.type === \"datetime\") &&\n (value instanceof Date || typeof value === \"string\")\n ) {\n const fmtValue = col.format as string | undefined;\n const fmt =\n col.type === \"date\"\n ? coerceDatePattern(fmtValue, \"date\")\n : col.type === \"time\"\n ? coerceDatePattern(fmtValue, \"time\")\n : coerceDatePattern(fmtValue, \"datetime\");\n let d: Date | null = null;\n if (value instanceof Date) d = value;\n else {\n d = parseIsoDate(value);\n }\n if (!d) return { text: String(value) };\n return { text: formatDateLite(d, fmt) };\n }\n return { text: String(value) };\n}\n\nfunction resolveTagValues(value: unknown): string[] | null {\n if (Array.isArray(value) && value.every((v) => typeof v === \"string\")) {\n return value as string[];\n }\n if (value && typeof value === \"object\") {\n const obj = value as Record<string, unknown>;\n if (obj.kind === \"tags\") {\n const values = obj.values;\n if (Array.isArray(values)) {\n return values.filter((v): v is string => typeof v === \"string\");\n }\n }\n }\n return null;\n}\n\nfunction resolvedStyleToMap(style: ResolvedCellStyle): CSSStyleMap {\n const css: CSSStyleMap = {};\n if (style.backgroundColor) css.backgroundColor = style.backgroundColor;\n if (style.textColor) css.color = style.textColor;\n if (style.bold) css.fontWeight = \"600\";\n if (style.italic) css.fontStyle = \"italic\";\n const dec: string[] = [];\n if (style.underline) dec.push(\"underline\");\n if (style.strike) dec.push(\"line-through\");\n if (dec.length) css.textDecorationLine = dec.join(\" \");\n return css;\n}\n\nfunction getColumnSortDir(view: View, colKey: string): \"asc\" | \"desc\" | null {\n const s = view.sorts?.[0];\n if (!s) return null;\n return s.key === colKey ? s.dir : null;\n}\n\nfunction hasActiveColumnFilter(view: View, colKey: string): boolean {\n const hasValues = (view.filters ?? []).some((f) => {\n const vf = f as ViewFilterValues;\n return vf?.kind === \"values\" && vf.key === colKey;\n });\n if (hasValues) return true;\n const diag = view.columnDiagnostics?.[colKey];\n return Boolean(diag?.errors || diag?.warnings);\n}\n\nfunction svgFunnel() {\n return `\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M3 5h18l-7 8v6l-4 2v-8L3 5z\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n </svg>\n `.trim();\n}\n\nfunction svgArrow(dir: \"asc\" | \"desc\") {\n const d = dir === \"asc\" ? \"M12 6l6 8H6l6-8z\" : \"M12 18l-6-8h12l-6 8z\";\n return `\n <svg viewBox=\"0 0 24 24\" width=\"16\" height=\"16\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"${d}\" fill=\"currentColor\"/>\n </svg>\n `.trim();\n}\n"],"names":["HTMLBuilder","tag","attrs","html","key","value","escapeHtml","content","text","serializeStyle","style","parts","prop","toKebabCase","CSSBuilder","selector","prev","options","minify","lines","body","input","m","renderTableHTML","cssMode","cssClassName","includeDataAttributes","includeAccessibilityAttributes","view","data","baseView","dataModel","DataModel","schema","effectiveView","rows","columns","resolveVisibleColumns","colWidths","getColumnWidths","cssBuilder","errors","rootSelector","col","baseStyle","resolvedStyleToMap","columnFormatToStyle","totalWidth","ROW_HEADER_WIDTH_PX","acc","w","tableAttrs","HEADER_HEIGHT_PX","rowHeaderAttrs","thAttrs","sortDir","getColumnSortDir","hasFilter","hasActiveColumnFilter","width","c","svgArrow","svgFunnel","hasFormulas","hasConditionalStyles","row","rowIndex","trAttrs","DEFAULT_ROW_HEIGHT_PX","rowHeader","displayIndex","renderCell","visibility","hidden","k","colMap","ordered","seen","order","isVisibleColumn","onFormulaError","onValidationError","tdClasses","interaction","wrap","align","condRes","cellStyle","withCond","mergeStyle","resolved","marker","raw","valueRes","textOverride","err","replacement","validationMsg","formatted","formatValue","resolvedWithFormat","tagValues","resolveTagValues","isActionType","actionValue","resolveButtonAction","resolveLinkAction","actionLabel","getButtonLabel","getLinkLabel","tdAttrs","rawNumbered","toRawValue","rawStr","inlineStyle","index","actionAttrs","tags","obj","num","fmt","formatNumberForEdit","color","opts","token","formatIntegerWithPrefix","fmtValue","coerceDatePattern","d","parseIsoDate","formatDateLite","v","values","css","dec","colKey","s","f","vf","diag","dir"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const isBrowser: boolean;
|
|
2
|
+
export declare function getDefaultLocale(): string;
|
|
3
|
+
export declare function getNavigator(): Navigator | {
|
|
4
|
+
language?: string;
|
|
5
|
+
userAgent?: string;
|
|
6
|
+
platform?: string;
|
|
7
|
+
};
|
|
8
|
+
export declare const ResizeObserverShim: typeof ResizeObserver | (new () => {
|
|
9
|
+
observe: () => void;
|
|
10
|
+
unobserve: () => void;
|
|
11
|
+
disconnect: () => void;
|
|
12
|
+
});
|
|
13
|
+
export declare function getRequestAnimationFrame(): (cb: FrameRequestCallback) => number;
|
|
14
|
+
export declare function getCancelAnimationFrame(): (id: number | ReturnType<typeof setTimeout>) => void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Schema } from "../types";
|
|
2
|
+
export interface SSROptions<T extends object = Record<string, unknown>> {
|
|
3
|
+
data: T[] | null | undefined;
|
|
4
|
+
schema: Schema<any>;
|
|
5
|
+
cssMode?: "inline" | "external" | "both";
|
|
6
|
+
wrapWithRoot?: boolean;
|
|
7
|
+
defaultClass?: string | string[];
|
|
8
|
+
defaultStyle?: Partial<CSSStyleDeclaration>;
|
|
9
|
+
includeStyles?: boolean;
|
|
10
|
+
includeRawAttributes?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export interface SSRResult {
|
|
13
|
+
html: string;
|
|
14
|
+
css?: string;
|
|
15
|
+
metadata: {
|
|
16
|
+
rowCount: number;
|
|
17
|
+
columnCount: number;
|
|
18
|
+
hasFormulas: boolean;
|
|
19
|
+
hasConditionalStyles: boolean;
|
|
20
|
+
errors: Array<{
|
|
21
|
+
row: number;
|
|
22
|
+
col: string;
|
|
23
|
+
message: string;
|
|
24
|
+
}>;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export declare function renderTableHTML<T extends object = Record<string, unknown>>(options: SSROptions<T>): SSRResult;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type CSSValue = string | number | null | undefined | false;
|
|
2
|
+
export type CSSStyleMap = Record<string, CSSValue>;
|
|
3
|
+
export declare function serializeStyle(style: CSSStyleMap): string;
|
|
4
|
+
export declare class CSSBuilder {
|
|
5
|
+
private rules;
|
|
6
|
+
addRule(selector: string, style: CSSStyleMap): void;
|
|
7
|
+
build(options?: {
|
|
8
|
+
minify?: boolean;
|
|
9
|
+
}): string;
|
|
10
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type CellValue = CellPrimitive | Date | {
|
|
|
16
16
|
kind: "tags";
|
|
17
17
|
values: string[];
|
|
18
18
|
} | ButtonValue | LinkValue;
|
|
19
|
-
export type ColumnType = "string" | "number" | "boolean" | "datetime" | "date" | "time" | "enum" | "tags" | "button" | "link";
|
|
19
|
+
export type ColumnType = "string" | "number" | "int" | "uint" | "boolean" | "datetime" | "date" | "time" | "enum" | "tags" | "button" | "link";
|
|
20
20
|
export type StringFormat = {
|
|
21
21
|
maxLength?: number;
|
|
22
22
|
regex?: string;
|
|
@@ -27,13 +27,30 @@ export type NumberFormat = {
|
|
|
27
27
|
signed?: boolean;
|
|
28
28
|
thousandSeparator?: boolean;
|
|
29
29
|
negativeRed?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Format token for number display.
|
|
32
|
+
* - "decimal": normal decimal formatting (default)
|
|
33
|
+
* - "scientific": scientific notation
|
|
34
|
+
* - other strings are reserved for future/custom formatters
|
|
35
|
+
*/
|
|
36
|
+
format?: string;
|
|
37
|
+
};
|
|
38
|
+
export type IntegerFormat = {
|
|
39
|
+
thousandSeparator?: boolean;
|
|
40
|
+
negativeRed?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Format token for integer display.
|
|
43
|
+
* - "decimal": normal decimal formatting (default)
|
|
44
|
+
* - "binary" | "octal" | "hex": prefixed base literals
|
|
45
|
+
* - other strings are reserved for future/custom formatters
|
|
46
|
+
*/
|
|
30
47
|
format?: string;
|
|
31
48
|
};
|
|
32
49
|
export type BooleanFormat = "checkbox" | string | [string, string];
|
|
33
50
|
export type DateFormat = string;
|
|
34
51
|
export type TimeFormat = string;
|
|
35
52
|
export type DateTimeFormat = string;
|
|
36
|
-
export type ColumnFormat<TType extends ColumnType> = TType extends "string" ? StringFormat : TType extends "number" ? NumberFormat : TType extends "boolean" ? BooleanFormat : TType extends "date" ? DateFormat : TType extends "time" ? TimeFormat : TType extends "datetime" ? DateTimeFormat : never;
|
|
53
|
+
export type ColumnFormat<TType extends ColumnType> = TType extends "string" ? StringFormat : TType extends "number" ? NumberFormat : TType extends "int" | "uint" ? IntegerFormat : TType extends "boolean" ? BooleanFormat : TType extends "date" ? DateFormat : TType extends "time" ? TimeFormat : TType extends "datetime" ? DateTimeFormat : never;
|
|
37
54
|
export type ResolvedCellStyle = {
|
|
38
55
|
backgroundColor?: string;
|
|
39
56
|
textColor?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@extable/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -10,11 +10,17 @@
|
|
|
10
10
|
"import": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts"
|
|
12
12
|
},
|
|
13
|
-
"./
|
|
13
|
+
"./ssr": {
|
|
14
|
+
"import": "./dist/ssr/index.js",
|
|
15
|
+
"types": "./dist/ssr/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./style.css": "./style.css",
|
|
14
18
|
"./index.css": "./dist/index.css"
|
|
15
19
|
},
|
|
16
20
|
"files": [
|
|
17
|
-
"dist"
|
|
21
|
+
"dist",
|
|
22
|
+
"style.css",
|
|
23
|
+
"src/styles.css"
|
|
18
24
|
],
|
|
19
25
|
"publishConfig": {
|
|
20
26
|
"access": "public"
|
|
@@ -31,7 +37,7 @@
|
|
|
31
37
|
"format": "biome format --write ."
|
|
32
38
|
},
|
|
33
39
|
"dependencies": {
|
|
34
|
-
"@extable/sequence": "0.3.
|
|
40
|
+
"@extable/sequence": "0.3.4"
|
|
35
41
|
},
|
|
36
42
|
"devDependencies": {
|
|
37
43
|
"typescript": "^5.6.3"
|