@stackcraftmx/calcita 0.56.0 → 0.58.0
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/README.md +83 -4
- package/dist/DataTable/ServerTableFilterDrawer.js +3 -1
- package/dist/DataTable/ServerTableFilterDrawer.js.map +1 -1
- package/dist/locales/en.js +15 -0
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +15 -0
- package/dist/locales/es.js.map +1 -1
- package/dist/sortable/FormSortableField.js +27 -0
- package/dist/sortable/FormSortableField.js.map +1 -0
- package/dist/sortable/SortableTable.js +230 -0
- package/dist/sortable/SortableTable.js.map +1 -0
- package/dist/sortable/sortableRows.js +14 -0
- package/dist/sortable/sortableRows.js.map +1 -0
- package/dist/sortable.js +9 -0
- package/dist/sortable.js.map +1 -0
- package/dist/theme/components/minimalComponents.js +15 -0
- package/dist/theme/components/minimalComponents.js.map +1 -1
- package/dist/theme/glassSurface.js +10 -12
- package/dist/theme/glassSurface.js.map +1 -1
- package/dist/theme/themePieces.js +10 -4
- package/dist/theme/themePieces.js.map +1 -1
- package/dist/types/DataTable/ServerTableFilterDrawer.d.ts +2 -0
- package/dist/types/downloads/fileTypes.d.ts +4 -4
- package/dist/types/forms/SubmitButton.d.ts +1 -1
- package/dist/types/locales/en.d.ts +15 -0
- package/dist/types/locales/es.d.ts +15 -0
- package/dist/types/sortable/FormSortableField.d.ts +15 -0
- package/dist/types/sortable/SortableTable.d.ts +77 -0
- package/dist/types/sortable/sortableRows.d.ts +12 -0
- package/dist/types/sortable.d.ts +3 -0
- package/dist/types/ui/filters/FilterDrawer.d.ts +1 -0
- package/dist/types/ui/filters/filterDrawerFields.d.ts +77 -2
- package/dist/ui/filters/FilterDrawer.js +118 -53
- package/dist/ui/filters/FilterDrawer.js.map +1 -1
- package/dist/ui/filters/filterDrawerFields.js +65 -14
- package/dist/ui/filters/filterDrawerFields.js.map +1 -1
- package/package.json +5 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filterDrawerFields.js","sources":["../../../src/ui/filters/filterDrawerFields.js"],"sourcesContent":["// Los campos del cajón de búsqueda (FilterDrawer): cómo viaja cada uno en los filtros de la lista, cuántos hay puestos y\n// cómo se dicen en sus chips. Un campo se declara una vez y de ahí sale todo:\n//\n// text un texto {name}: 'ana'\n// select una opción {name}: 'card'\n// multiSelect varias opciones (lista) {name}: ['card', 'cash']\n// catalog una o varias de un catálogo largo {name}: 'NL' o ['NL', 'JA'] (multiple)\n// checkboxes varias, a la vista {name}: ['email', 'sms']\n// numberRange desde y hasta {name}_min: '3', {name}_max: '10'\n// dateRange del día al día (AAAA-MM-DD) {name}_from: '2026-11-01', {name}_to: '2026-11-30'\n// comparison un número con su operador {name}: 'gte:500' (mayor o igual que 500)\n// custom uno propio (render) {name}: lo que el proyecto decida\n//\n// Los nombres de un rango se cambian con keys ({from: 'created_from', to: 'created_to'}) para usar los que ya tiene el\n// backend. Los textos llegan ya traducidos (label, options[].label); los de la casa salen de `t` (common.filterDrawer).\n//\n// Puro (sin React): se prueba con node (filterDrawerFields.test.js).\n//\n// Genérico del paquete: function (regla de la casa).\n\n/** Los tipos de campo del cajón. */\nexport const FILTER_FIELD_KIND = Object.freeze({\n text: 'text', select: 'select', multiSelect: 'multiSelect', catalog: 'catalog', checkboxes: 'checkboxes',\n numberRange: 'numberRange', dateRange: 'dateRange', comparison: 'comparison', custom: 'custom',\n});\n\n/** Los operadores de un campo de comparación, como viajan ('gte:500'). */\nexport const COMPARISON_OPERATOR = Object.freeze({equals: 'eq', greaterThan: 'gt', greaterOrEqual: 'gte', lessThan: 'lt', lessOrEqual: 'lte'});\n\n// cómo se dice cada operador en un chip, corto\nconst OPERATOR_SYMBOLS = Object.freeze({eq: '=', gt: '>', gte: '≥', lt: '<', lte: '≤'});\nconst COMPARISON_SEPARATOR = ':';\n// los que guardan una lista: así los lee la tabla en la dirección\nconst LIST_KINDS = new Set([FILTER_FIELD_KIND.multiSelect, FILTER_FIELD_KIND.checkboxes]);\n\n/**\n * ¿El campo guarda una lista?\n *\n * @param {{kind: string, multiple?: boolean}} field\n * @returns {boolean}\n */\nexport function isListField(field) {\n return LIST_KINDS.has(field.kind) || (field.kind === FILTER_FIELD_KIND.catalog && Boolean(field.multiple));\n}\n\n/**\n * Los nombres con que viaja un campo en los filtros: uno, o dos para un rango.\n *\n * @param {{name: string, kind: string, keys?: {from?: string, to?: string}}} field\n * @returns {string[]}\n */\nexport function filterKeysOf(field) {\n if (field.kind === FILTER_FIELD_KIND.numberRange) {\n return [field.keys?.from ?? `${field.name}_min`, field.keys?.to ?? `${field.name}_max`];\n }\n if (field.kind === FILTER_FIELD_KIND.dateRange) {\n return [field.keys?.from ?? `${field.name}_from`, field.keys?.to ?? `${field.name}_to`];\n }\n return [field.name];\n}\n\n/**\n * Un valor de comparación ('gte:500') en sus partes; null si viene vacío o no se entiende.\n *\n * @param {unknown} text\n * @returns {{operator: string, value: string}|null}\n */\nexport function comparisonOf(text) {\n const [operator, ...rest] = String(text ?? '').split(COMPARISON_SEPARATOR);\n const value = rest.join(COMPARISON_SEPARATOR);\n return OPERATOR_SYMBOLS[operator] && value !== '' ? {operator, value} : null;\n}\n\n/**\n * Las partes de una comparación como viajan; '' si falta el número.\n *\n * @param {string} operator COMPARISON_OPERATOR\n * @param {string} value\n * @returns {string}\n */\nexport function comparisonTextOf(operator, value) {\n return value === '' || value === null || value === undefined ? '' : `${operator}${COMPARISON_SEPARATOR}${value}`;\n}\n\n/**\n * ¿Ese valor de filtro está puesto? Un texto vacío o una lista vacía no cuentan.\n *\n * @param {unknown} value\n * @returns {boolean}\n */\nexport function isFilterValueSet(value) {\n return Array.isArray(value) ? value.length > 0 : value !== '' && value !== null && value !== undefined;\n}\n\n/**\n * Los tipos de filtro para ServerTable (filterKinds): los de lista se leen como lista en la dirección.\n *\n * @param {object[]} fields\n * @returns {Record<string, string>}\n */\nexport function filterDrawerKindsOf(fields) {\n return Object.fromEntries(fields.filter(isListField).map((field) => [field.name, 'multiSelect']));\n}\n\n/**\n * Lo que hay en los filtros para los campos del cajón (lo demás no se toca).\n *\n * @param {object[]} fields\n * @param {Record<string, unknown>} filters\n * @returns {Record<string, unknown>}\n */\nexport function drawerValuesOf(fields, filters) {\n return Object.fromEntries(fields.flatMap((field) => filterKeysOf(field).map((key) => [key, filters?.[key] ?? (isListField(field) ? [] : '')])));\n}\n\n/**\n * Los campos del cajón vacíos: lo que deja «Limpiar».\n *\n * @param {object[]} fields\n * @returns {Record<string, unknown>}\n */\nexport function emptyDrawerValuesOf(fields) {\n return drawerValuesOf(fields, {});\n}\n\n/**\n * Los campos del cajón vacíos, para sumarlos a filterDefaults de ServerTable: la tabla solo guarda en la dirección los\n * filtros que declara ahí.\n *\n * @param {object[]} fields\n * @returns {Record<string, unknown>}\n */\nexport function filterDrawerDefaultsOf(fields) {\n return emptyDrawerValuesOf(fields);\n}\n\n/**\n * Cuántos campos del cajón tienen algo puesto (un rango con «desde» y «hasta» cuenta uno): el número del botón «Filtros».\n *\n * @param {object[]} fields\n * @param {Record<string, unknown>} filters\n * @returns {number}\n */\nexport function activeDrawerFilterCountOf(fields, filters) {\n return fields.filter((field) => filterKeysOf(field).some((key) => isFilterValueSet(filters?.[key]))).length;\n}\n\n/**\n * Los rangos que no tienen sentido («hasta» menor que «desde»): {llave de «hasta»: true}.\n *\n * @param {object[]} fields\n * @param {Record<string, unknown>} values\n * @returns {Record<string, boolean>}\n */\nexport function invalidRangesOf(fields, values) {\n const invalid = {};\n for (const field of fields) {\n if (field.kind !== FILTER_FIELD_KIND.numberRange && field.kind !== FILTER_FIELD_KIND.dateRange) {\n continue;\n }\n const [fromKey, toKey] = filterKeysOf(field);\n const from = values?.[fromKey];\n const to = values?.[toKey];\n if (!isFilterValueSet(from) || !isFilterValueSet(to)) {\n continue;\n }\n // los números como números y las fechas AAAA-MM-DD como texto (ya se ordenan solas)\n const isBackwards = field.kind === FILTER_FIELD_KIND.numberRange ? Number(to) < Number(from) : String(to) < String(from);\n if (isBackwards) {\n invalid[toKey] = true;\n }\n }\n return invalid;\n}\n\n/**\n * Los chips de los campos del cajón, con la forma de buildChipConfig: cada valor con su etiqueta, ya dicho en palabras.\n *\n * @param {object[]} fields\n * @param {object} helpers\n * @param {(key: string, values?: object) => string} helpers.t el de common (filterDrawer.chipFrom, chipTo)\n * @param {(date: string) => string} [helpers.formatDate] cómo se ve una fecha\n * @returns {{text: Array<{key: string, label: string, format?: (value: string) => string}>, multiSelect: Array<{key: string, label: string, itemLabel?: (value: string) => string}>}}\n */\nexport function filterDrawerChipsOf(fields, {t, formatDate = (date) => date}) {\n const text = [];\n const multiSelect = [];\n const optionLabelOf = (field, value) => field.options?.find((option) => (option.value ?? option.code) === value)?.label ?? String(value);\n for (const field of fields) {\n const withUnit = (value) => `${field.prefix ?? ''}${value}${field.suffix ? ` ${field.suffix}` : ''}`;\n if (isListField(field)) {\n multiSelect.push({key: field.name, label: field.label, itemLabel: (value) => optionLabelOf(field, value)});\n } else if (field.kind === FILTER_FIELD_KIND.numberRange || field.kind === FILTER_FIELD_KIND.dateRange) {\n const [fromKey, toKey] = filterKeysOf(field);\n const format = field.kind === FILTER_FIELD_KIND.dateRange ? formatDate : withUnit;\n text.push({key: fromKey, label: t('filterDrawer.chipFrom', {label: field.label}), format});\n text.push({key: toKey, label: t('filterDrawer.chipTo', {label: field.label}), format});\n } else if (field.kind === FILTER_FIELD_KIND.comparison) {\n text.push({\n key: field.name, label: field.label,\n format: (value) => {\n const parts = comparisonOf(value);\n return parts ? `${OPERATOR_SYMBOLS[parts.operator]} ${withUnit(parts.value)}` : String(value);\n },\n });\n } else if (field.kind === FILTER_FIELD_KIND.select || field.kind === FILTER_FIELD_KIND.catalog) {\n text.push({key: field.name, label: field.label, format: (value) => optionLabelOf(field, value)});\n } else {\n text.push({key: field.name, label: field.label, ...(field.chipFormat && {format: field.chipFormat})});\n }\n }\n return {text, multiSelect};\n}\n"],"names":[],"mappings":"AAqBY,MAAC,oBAAoB,OAAO,OAAO;AAAA,EAC3C,MAAM;AAAA,EAAQ,QAAQ;AAAA,EAAU,aAAa;AAAA,EAAe,SAAS;AAAA,EAAW,YAAY;AAAA,EAC5F,aAAa;AAAA,EAAe,WAAW;AAAA,EAAa,YAAY;AAAA,EAAc,QAAQ;AAC1F,CAAC;AAGW,MAAC,sBAAsB,OAAO,OAAO,EAAC,QAAQ,MAAM,aAAa,MAAM,gBAAgB,OAAO,UAAU,MAAM,aAAa,MAAK,CAAC;AAG7I,MAAM,mBAAmB,OAAO,OAAO,EAAC,IAAI,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,IAAG,CAAC;AACtF,MAAM,uBAAuB;AAE7B,MAAM,aAAa,oBAAI,IAAI,CAAC,kBAAkB,aAAa,kBAAkB,UAAU,CAAC;AAQjF,SAAS,YAAY,OAAO;AAC/B,SAAO,WAAW,IAAI,MAAM,IAAI,KAAM,MAAM,SAAS,kBAAkB,WAAW,QAAQ,MAAM,QAAQ;AAC5G;AAQO,SAAS,aAAa,OAAO;AAChC,MAAI,MAAM,SAAS,kBAAkB,aAAa;AAC9C,WAAO,CAAC,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,QAAQ,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,MAAM;AAAA,EAC1F;AACA,MAAI,MAAM,SAAS,kBAAkB,WAAW;AAC5C,WAAO,CAAC,MAAM,MAAM,QAAQ,GAAG,MAAM,IAAI,SAAS,MAAM,MAAM,MAAM,GAAG,MAAM,IAAI,KAAK;AAAA,EAC1F;AACA,SAAO,CAAC,MAAM,IAAI;AACtB;AAQO,SAAS,aAAa,MAAM;AAC/B,QAAM,CAAC,UAAU,GAAG,IAAI,IAAI,OAAO,QAAQ,EAAE,EAAE,MAAM,oBAAoB;AACzE,QAAM,QAAQ,KAAK,KAAK,oBAAoB;AAC5C,SAAO,iBAAiB,QAAQ,KAAK,UAAU,KAAK,EAAC,UAAU,MAAK,IAAI;AAC5E;AASO,SAAS,iBAAiB,UAAU,OAAO;AAC9C,SAAO,UAAU,MAAM,UAAU,QAAQ,UAAU,SAAY,KAAK,GAAG,QAAQ,GAAG,oBAAoB,GAAG,KAAK;AAClH;AAQO,SAAS,iBAAiB,OAAO;AACpC,SAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,SAAS,IAAI,UAAU,MAAM,UAAU,QAAQ,UAAU;AACjG;AAQO,SAAS,oBAAoB,QAAQ;AACxC,SAAO,OAAO,YAAY,OAAO,OAAO,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,MAAM,aAAa,CAAC,CAAC;AACpG;AASO,SAAS,eAAe,QAAQ,SAAS;AAC5C,SAAO,OAAO,YAAY,OAAO,QAAQ,CAAC,UAAU,aAAa,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,UAAU,GAAG,MAAM,YAAY,KAAK,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;AAClJ;AAQO,SAAS,oBAAoB,QAAQ;AACxC,SAAO,eAAe,QAAQ,EAAE;AACpC;AASO,SAAS,uBAAuB,QAAQ;AAC3C,SAAO,oBAAoB,MAAM;AACrC;AASO,SAAS,0BAA0B,QAAQ,SAAS;AACvD,SAAO,OAAO,OAAO,CAAC,UAAU,aAAa,KAAK,EAAE,KAAK,CAAC,QAAQ,iBAAiB,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE;AACzG;AASO,SAAS,gBAAgB,QAAQ,QAAQ;AAC5C,QAAM,UAAU,CAAA;AAChB,aAAW,SAAS,QAAQ;AACxB,QAAI,MAAM,SAAS,kBAAkB,eAAe,MAAM,SAAS,kBAAkB,WAAW;AAC5F;AAAA,IACJ;AACA,UAAM,CAAC,SAAS,KAAK,IAAI,aAAa,KAAK;AAC3C,UAAM,OAAO,SAAS,OAAO;AAC7B,UAAM,KAAK,SAAS,KAAK;AACzB,QAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,EAAE,GAAG;AAClD;AAAA,IACJ;AAEA,UAAM,cAAc,MAAM,SAAS,kBAAkB,cAAc,OAAO,EAAE,IAAI,OAAO,IAAI,IAAI,OAAO,EAAE,IAAI,OAAO,IAAI;AACvH,QAAI,aAAa;AACb,cAAQ,KAAK,IAAI;AAAA,IACrB;AAAA,EACJ;AACA,SAAO;AACX;AAWO,SAAS,oBAAoB,QAAQ,EAAC,GAAG,aAAa,CAAC,SAAS,KAAI,GAAG;AAC1E,QAAM,OAAO,CAAA;AACb,QAAM,cAAc,CAAA;AACpB,QAAM,gBAAgB,CAAC,OAAO,UAAU,MAAM,SAAS,KAAK,CAAC,YAAY,OAAO,SAAS,OAAO,UAAU,KAAK,GAAG,SAAS,OAAO,KAAK;AACvI,aAAW,SAAS,QAAQ;AACxB,UAAM,WAAW,CAAC,UAAU,GAAG,MAAM,UAAU,EAAE,GAAG,KAAK,GAAG,MAAM,SAAS,IAAI,MAAM,MAAM,KAAK,EAAE;AAClG,QAAI,YAAY,KAAK,GAAG;AACpB,kBAAY,KAAK,EAAC,KAAK,MAAM,MAAM,OAAO,MAAM,OAAO,WAAW,CAAC,UAAU,cAAc,OAAO,KAAK,EAAC,CAAC;AAAA,IAC7G,WAAW,MAAM,SAAS,kBAAkB,eAAe,MAAM,SAAS,kBAAkB,WAAW;AACnG,YAAM,CAAC,SAAS,KAAK,IAAI,aAAa,KAAK;AAC3C,YAAM,SAAS,MAAM,SAAS,kBAAkB,YAAY,aAAa;AACzE,WAAK,KAAK,EAAC,KAAK,SAAS,OAAO,EAAE,yBAAyB,EAAC,OAAO,MAAM,MAAK,CAAC,GAAG,OAAM,CAAC;AACzF,WAAK,KAAK,EAAC,KAAK,OAAO,OAAO,EAAE,uBAAuB,EAAC,OAAO,MAAM,MAAK,CAAC,GAAG,OAAM,CAAC;AAAA,IACzF,WAAW,MAAM,SAAS,kBAAkB,YAAY;AACpD,WAAK,KAAK;AAAA,QACN,KAAK,MAAM;AAAA,QAAM,OAAO,MAAM;AAAA,QAC9B,QAAQ,CAAC,UAAU;AACf,gBAAM,QAAQ,aAAa,KAAK;AAChC,iBAAO,QAAQ,GAAG,iBAAiB,MAAM,QAAQ,CAAC,IAAI,SAAS,MAAM,KAAK,CAAC,KAAK,OAAO,KAAK;AAAA,QAChG;AAAA,MAChB,CAAa;AAAA,IACL,WAAW,MAAM,SAAS,kBAAkB,UAAU,MAAM,SAAS,kBAAkB,SAAS;AAC5F,WAAK,KAAK,EAAC,KAAK,MAAM,MAAM,OAAO,MAAM,OAAO,QAAQ,CAAC,UAAU,cAAc,OAAO,KAAK,EAAC,CAAC;AAAA,IACnG,OAAO;AACH,WAAK,KAAK,EAAC,KAAK,MAAM,MAAM,OAAO,MAAM,OAAO,GAAI,MAAM,cAAc,EAAC,QAAQ,MAAM,WAAU,EAAE,CAAC;AAAA,IACxG;AAAA,EACJ;AACA,SAAO,EAAC,MAAM,YAAW;AAC7B;"}
|
|
1
|
+
{"version":3,"file":"filterDrawerFields.js","sources":["../../../src/ui/filters/filterDrawerFields.js"],"sourcesContent":["// Los campos del cajón de búsqueda (FilterDrawer): cómo viaja cada uno en los filtros de la lista, cuántos hay puestos y\n// cómo se dicen en sus chips. Un campo se declara una vez y de ahí sale todo:\n//\n// text un texto {name}: 'ana'\n// select una opción {name}: 'card'\n// multiSelect varias opciones (lista) {name}: ['card', 'cash']\n// catalog una o varias de un catálogo largo {name}: 'NL' o ['NL', 'JA'] (multiple)\n// checkboxes varias, a la vista {name}: ['email', 'sms']\n// numberRange desde y hasta {name}_min: '3', {name}_max: '10'\n// dateRange del día al día (AAAA-MM-DD) {name}_from: '2026-11-01', {name}_to: '2026-11-30'\n// comparison un número con su operador {name}: 'gte:500' (mayor o igual que 500)\n// custom uno propio (render) {name}: lo que el proyecto decida\n// o un rango propio, con keys {keys.from}: …, {keys.to}: …\n//\n// Los nombres de un rango se cambian con keys ({from: 'created_from', to: 'created_to'}) para usar los que ya tiene el\n// backend. Un custom con keys es un rango propio: guarda en sus dos llaves, cuenta como un filtro, da dos chips («desde» y\n// «hasta») y, con isBackwards(from, to), no deja buscar si está al revés, como los de la casa.\n//\n// Un dateRange se acota con minDate y maxDate ('AAAA-MM-DD'), disablePast y disableFuture (hoy en la zona del producto): el\n// calendario no deja escoger fuera, cada extremo acota al otro y lo que se teclee fuera se dice en su campo y no deja buscar\n// (drawerProblemsOf). Nada se borra solo.\n//\n// Los textos llegan ya traducidos (label, options[].label); los de la casa salen de `t` (common.filterDrawer).\n//\n// Puro (sin React): se prueba con node (filterDrawerFields.test.js).\n//\n// Genérico del paquete: function (regla de la casa).\n\n/** Los tipos de campo del cajón. */\nexport const FILTER_FIELD_KIND = Object.freeze({\n text: 'text', select: 'select', multiSelect: 'multiSelect', catalog: 'catalog', checkboxes: 'checkboxes',\n numberRange: 'numberRange', dateRange: 'dateRange', comparison: 'comparison', custom: 'custom',\n});\n\n/**\n * Lo que puede estar mal en un campo del cajón; cada uno es su texto en common.filterDrawer. Mientras haya uno, «Buscar» no\n * busca.\n */\nexport const FILTER_FIELD_PROBLEM = Object.freeze({rangeBackwards: 'rangeBackwards', beforeMinDate: 'dateBeforeMin', afterMaxDate: 'dateAfterMax'});\n\n/** Los operadores de un campo de comparación, como viajan ('gte:500'). */\nexport const COMPARISON_OPERATOR = Object.freeze({equals: 'eq', greaterThan: 'gt', greaterOrEqual: 'gte', lessThan: 'lt', lessOrEqual: 'lte'});\n\n// cómo se dice cada operador en un chip, corto\nconst OPERATOR_SYMBOLS = Object.freeze({eq: '=', gt: '>', gte: '≥', lt: '<', lte: '≤'});\nconst COMPARISON_SEPARATOR = ':';\n// los que guardan una lista: así los lee la tabla en la dirección\nconst LIST_KINDS = new Set([FILTER_FIELD_KIND.multiSelect, FILTER_FIELD_KIND.checkboxes]);\n\n/**\n * ¿El campo guarda una lista?\n *\n * @param {{kind: string, multiple?: boolean}} field\n * @returns {boolean}\n */\nexport function isListField(field) {\n return LIST_KINDS.has(field.kind) || (field.kind === FILTER_FIELD_KIND.catalog && Boolean(field.multiple));\n}\n\n/**\n * ¿El campo es un rango propio? Un custom con sus dos llaves (keys.from y keys.to).\n *\n * @param {{kind: string, keys?: {from?: string, to?: string}}} field\n * @returns {boolean}\n */\nfunction isCustomRange(field) {\n return field.kind === FILTER_FIELD_KIND.custom && Boolean(field.keys?.from) && Boolean(field.keys?.to);\n}\n\n/**\n * ¿El campo guarda un «desde» y un «hasta»? Los rangos de la casa y los propios.\n *\n * @param {{kind: string, keys?: {from?: string, to?: string}}} field\n * @returns {boolean}\n */\nexport function isRangeField(field) {\n return field.kind === FILTER_FIELD_KIND.numberRange || field.kind === FILTER_FIELD_KIND.dateRange || isCustomRange(field);\n}\n\n/**\n * Los nombres con que viaja un campo en los filtros: uno, o dos para un rango (también uno propio: custom con keys).\n *\n * @param {{name: string, kind: string, keys?: {from?: string, to?: string}}} field\n * @returns {string[]}\n */\nexport function filterKeysOf(field) {\n if (field.kind === FILTER_FIELD_KIND.numberRange) {\n return [field.keys?.from ?? `${field.name}_min`, field.keys?.to ?? `${field.name}_max`];\n }\n if (field.kind === FILTER_FIELD_KIND.dateRange) {\n return [field.keys?.from ?? `${field.name}_from`, field.keys?.to ?? `${field.name}_to`];\n }\n if (isCustomRange(field)) {\n return [field.keys.from, field.keys.to];\n }\n return [field.name];\n}\n\n/**\n * Un valor de comparación ('gte:500') en sus partes; null si viene vacío o no se entiende.\n *\n * @param {unknown} text\n * @returns {{operator: string, value: string}|null}\n */\nexport function comparisonOf(text) {\n const [operator, ...rest] = String(text ?? '').split(COMPARISON_SEPARATOR);\n const value = rest.join(COMPARISON_SEPARATOR);\n return OPERATOR_SYMBOLS[operator] && value !== '' ? {operator, value} : null;\n}\n\n/**\n * Las partes de una comparación como viajan; '' si falta el número.\n *\n * @param {string} operator COMPARISON_OPERATOR\n * @param {string} value\n * @returns {string}\n */\nexport function comparisonTextOf(operator, value) {\n return value === '' || value === null || value === undefined ? '' : `${operator}${COMPARISON_SEPARATOR}${value}`;\n}\n\n/**\n * ¿Ese valor de filtro está puesto? Un texto vacío o una lista vacía no cuentan.\n *\n * @param {unknown} value\n * @returns {boolean}\n */\nexport function isFilterValueSet(value) {\n return Array.isArray(value) ? value.length > 0 : value !== '' && value !== null && value !== undefined;\n}\n\n/**\n * Los tipos de filtro para ServerTable (filterKinds): los de lista se leen como lista en la dirección.\n *\n * @param {object[]} fields\n * @returns {Record<string, string>}\n */\nexport function filterDrawerKindsOf(fields) {\n return Object.fromEntries(fields.filter(isListField).map((field) => [field.name, 'multiSelect']));\n}\n\n/**\n * Lo que hay en los filtros para los campos del cajón (lo demás no se toca).\n *\n * @param {object[]} fields\n * @param {Record<string, unknown>} filters\n * @returns {Record<string, unknown>}\n */\nexport function drawerValuesOf(fields, filters) {\n return Object.fromEntries(fields.flatMap((field) => filterKeysOf(field).map((key) => [key, filters?.[key] ?? (isListField(field) ? [] : '')])));\n}\n\n/**\n * Los campos del cajón vacíos: lo que deja «Limpiar».\n *\n * @param {object[]} fields\n * @returns {Record<string, unknown>}\n */\nexport function emptyDrawerValuesOf(fields) {\n return drawerValuesOf(fields, {});\n}\n\n/**\n * Los campos del cajón vacíos, para sumarlos a filterDefaults de ServerTable: la tabla solo guarda en la dirección los\n * filtros que declara ahí.\n *\n * @param {object[]} fields\n * @returns {Record<string, unknown>}\n */\nexport function filterDrawerDefaultsOf(fields) {\n return emptyDrawerValuesOf(fields);\n}\n\n/**\n * Cuántos campos del cajón tienen algo puesto (un rango con «desde» y «hasta» cuenta uno): el número del botón «Filtros».\n *\n * @param {object[]} fields\n * @param {Record<string, unknown>} filters\n * @returns {number}\n */\nexport function activeDrawerFilterCountOf(fields, filters) {\n return fields.filter((field) => filterKeysOf(field).some((key) => isFilterValueSet(filters?.[key]))).length;\n}\n\n/**\n * ¿Ese rango está al revés («hasta» antes que «desde»)? Los números como números, las fechas AAAA-MM-DD como texto (ya se\n * ordenan solas) y uno propio con su isBackwards (sin él, nunca).\n */\nfunction isBackwardsRange(field, from, to) {\n if (field.kind === FILTER_FIELD_KIND.numberRange) {\n return Number(to) < Number(from);\n }\n if (field.kind === FILTER_FIELD_KIND.dateRange) {\n return String(to) < String(from);\n }\n return Boolean(field.isBackwards?.(from, to));\n}\n\n/**\n * Los rangos que no tienen sentido («hasta» menor que «desde»): {llave de «hasta»: true}. También los propios (custom con\n * keys) que traen isBackwards.\n *\n * @param {object[]} fields\n * @param {Record<string, unknown>} values\n * @returns {Record<string, boolean>}\n */\nexport function invalidRangesOf(fields, values) {\n const invalid = {};\n for (const field of fields.filter(isRangeField)) {\n const [fromKey, toKey] = filterKeysOf(field);\n const from = values?.[fromKey];\n const to = values?.[toKey];\n if (isFilterValueSet(from) && isFilterValueSet(to) && isBackwardsRange(field, from, to)) {\n invalid[toKey] = true;\n }\n }\n return invalid;\n}\n\n// la más temprana y la más tardía de unas fechas AAAA-MM-DD (las vacías no cuentan)\nconst earliestDateOf = (...dates) => dates.filter(Boolean).sort()[0];\nconst latestDateOf = (...dates) => dates.filter(Boolean).sort().at(-1);\n\n/**\n * Los topes de un dateRange: minDate y maxDate del campo, y hoy si pide disablePast o disableFuture (el más estrecho gana).\n *\n * @param {{minDate?: string, maxDate?: string, disablePast?: boolean, disableFuture?: boolean}} field\n * @param {string} today AAAA-MM-DD en la zona del producto (todayInZone)\n * @returns {{minDate?: string, maxDate?: string}}\n */\nexport function dateLimitsOf(field, today) {\n return {\n minDate: latestDateOf(field.minDate, field.disablePast && today),\n maxDate: earliestDateOf(field.maxDate, field.disableFuture && today),\n };\n}\n\n/**\n * Los topes de cada extremo de un dateRange para su calendario: los del campo y, además, cada extremo acota al otro (el\n * «desde» no pasa del «hasta» puesto y el «hasta» no baja del «desde»).\n *\n * @param {object} field\n * @param {Record<string, unknown>} values el borrador del cajón\n * @param {string} today AAAA-MM-DD en la zona del producto\n * @returns {{from: {minDate?: string, maxDate?: string}, to: {minDate?: string, maxDate?: string}}}\n */\nexport function dateRangeBoundsOf(field, values, today) {\n const [fromKey, toKey] = filterKeysOf(field);\n const {minDate, maxDate} = dateLimitsOf(field, today);\n return {\n from: {minDate, maxDate: earliestDateOf(maxDate, values?.[toKey] || undefined)},\n to: {minDate: latestDateOf(minDate, values?.[fromKey] || undefined), maxDate},\n };\n}\n\n/**\n * Lo que está mal en los campos del cajón, por llave: un rango al revés (en su «hasta») y una fecha fuera de los topes de\n * su dateRange (la que se tecleó: el calendario ya no deja escogerla). Mientras haya algo, «Buscar» no busca.\n *\n * {created_to: {problem: 'rangeBackwards'}, paid_from: {problem: 'dateBeforeMin', date: '2026-01-01'}}\n *\n * @param {object[]} fields\n * @param {Record<string, unknown>} values\n * @param {{today?: string}} [options] hoy AAAA-MM-DD en la zona del producto (para disablePast y disableFuture)\n * @returns {Record<string, {problem: string, date?: string}>} problem es FILTER_FIELD_PROBLEM; date, el tope que se pasó\n */\nexport function drawerProblemsOf(fields, values, {today} = {}) {\n const problems = Object.fromEntries(Object.keys(invalidRangesOf(fields, values)).map((key) => [key, {problem: FILTER_FIELD_PROBLEM.rangeBackwards}]));\n for (const field of fields.filter((candidate) => candidate.kind === FILTER_FIELD_KIND.dateRange)) {\n const {minDate, maxDate} = dateLimitsOf(field, today);\n for (const key of filterKeysOf(field)) {\n const date = values?.[key];\n if (!isFilterValueSet(date)) {\n continue;\n }\n if (minDate && String(date) < minDate) {\n problems[key] = {problem: FILTER_FIELD_PROBLEM.beforeMinDate, date: minDate};\n } else if (maxDate && String(date) > maxDate) {\n problems[key] = {problem: FILTER_FIELD_PROBLEM.afterMaxDate, date: maxDate};\n }\n }\n }\n return problems;\n}\n\n/**\n * Los chips de los campos del cajón, con la forma de buildChipConfig: cada valor con su etiqueta, ya dicho en palabras.\n *\n * @param {object[]} fields\n * @param {object} helpers\n * @param {(key: string, values?: object) => string} helpers.t el de common (filterDrawer.chipFrom, chipTo)\n * @param {(date: string) => string} [helpers.formatDate] cómo se ve una fecha\n * @returns {{text: Array<{key: string, label: string, format?: (value: string) => string}>, multiSelect: Array<{key: string, label: string, itemLabel?: (value: string) => string}>}}\n */\nexport function filterDrawerChipsOf(fields, {t, formatDate = (date) => date}) {\n const text = [];\n const multiSelect = [];\n const optionLabelOf = (field, value) => field.options?.find((option) => (option.value ?? option.code) === value)?.label ?? String(value);\n for (const field of fields) {\n const withUnit = (value) => `${field.prefix ?? ''}${value}${field.suffix ? ` ${field.suffix}` : ''}`;\n if (isListField(field)) {\n multiSelect.push({key: field.name, label: field.label, itemLabel: (value) => optionLabelOf(field, value)});\n } else if (isRangeField(field)) {\n const [fromKey, toKey] = filterKeysOf(field);\n // un rango propio se dice con su chipFormat (o tal cual)\n const format = field.kind === FILTER_FIELD_KIND.dateRange ? formatDate : (isCustomRange(field) ? field.chipFormat : withUnit);\n text.push({key: fromKey, label: t('filterDrawer.chipFrom', {label: field.label}), ...(format && {format})});\n text.push({key: toKey, label: t('filterDrawer.chipTo', {label: field.label}), ...(format && {format})});\n } else if (field.kind === FILTER_FIELD_KIND.comparison) {\n text.push({\n key: field.name, label: field.label,\n format: (value) => {\n const parts = comparisonOf(value);\n return parts ? `${OPERATOR_SYMBOLS[parts.operator]} ${withUnit(parts.value)}` : String(value);\n },\n });\n } else if (field.kind === FILTER_FIELD_KIND.select || field.kind === FILTER_FIELD_KIND.catalog) {\n text.push({key: field.name, label: field.label, format: (value) => optionLabelOf(field, value)});\n } else {\n text.push({key: field.name, label: field.label, ...(field.chipFormat && {format: field.chipFormat})});\n }\n }\n return {text, multiSelect};\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackcraftmx/calcita",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0",
|
|
4
4
|
"description": "Componentes y utilidades de React con MUI para arrancar proyectos rápido: tabla de servidor, diálogos, avisos, descargas, formularios, formatos y reportes en Excel.",
|
|
5
5
|
"license": "FSL-1.1-MIT",
|
|
6
6
|
"author": "calcifux",
|
|
@@ -139,6 +139,10 @@
|
|
|
139
139
|
"types": "./dist/types/kanban.d.ts",
|
|
140
140
|
"import": "./dist/kanban.js"
|
|
141
141
|
},
|
|
142
|
+
"./sortable": {
|
|
143
|
+
"types": "./dist/types/sortable.d.ts",
|
|
144
|
+
"import": "./dist/sortable.js"
|
|
145
|
+
},
|
|
142
146
|
"./package.json": "./package.json"
|
|
143
147
|
},
|
|
144
148
|
"scripts": {
|