@stackcraftmx/calcita 0.26.0 → 0.27.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 CHANGED
@@ -263,6 +263,19 @@ navegador: `isAndroidDevice({userAgent: headers.get('user-agent')})`. Sirve para
263
263
  const theme = isAndroidDevice() ? createToolkitTheme({look: THEME_LOOK.minimal}) : createToolkitTheme({glass: true});
264
264
  ```
265
265
 
266
+ El minimalista separa las superficies por su tono con los grises de Apple. Para pintarlo con los colores de la marca:
267
+ `minimalTones`, por modo, con el fondo de la página (`default`), las tarjetas (`paper`), el relleno de campos, grupos y
268
+ botones sin color (`fill`) y lo que flota, como la barra del teléfono (`floating`). Lo que no se pase se queda con el gris
269
+ de Apple (`MINIMAL_TONES`). Ojo: con el minimalista el fondo sale de aquí y no de la paleta.
270
+
271
+ ```js
272
+ createToolkitTheme({
273
+ colorSchemes: {light: {palette: brandLight}, dark: {palette: brandDark}},
274
+ look: THEME_LOOK.minimal,
275
+ minimalTones: {light: {default: '#EEF4FF', fill: '#DCE6F5'}, dark: {default: '#101827', paper: '#1A2333'}},
276
+ });
277
+ ```
278
+
266
279
  Para lo que el proyecto quiera hacer flotar (los botones encima de un mapa, una barra de acciones): `GlassPanel`, que es
267
280
  de vidrio si el tema lo trae y una tarjeta con sombra si no. Para algo propio: `sx={(theme) => glassStylesOf(theme)}` e
268
281
  `isGlassTheme(theme)`. Cada ajuste vive en su archivo (`src/theme/components/MuiButton.js`…).
package/dist/index.js CHANGED
@@ -21,7 +21,7 @@ import { DEFAULT_FILE_TYPES, UNKNOWN_FILE_TYPE, useFileTypes } from "./downloads
21
21
  import { DOWNLOAD_STATUS, downloadsMachine } from "./downloads/downloadsMachine.js";
22
22
  import { THEME_LOOK, TOP_BAR, createToolkitTheme } from "./theme/createToolkitTheme.js";
23
23
  import { isAndroidDevice } from "./theme/androidDevice.js";
24
- import { MINIMAL_BACKGROUND } from "./theme/components/minimalComponents.js";
24
+ import { MINIMAL_BACKGROUND, MINIMAL_TONES } from "./theme/components/minimalComponents.js";
25
25
  import { STACKCRAFT, stackcraftDarkPalette, stackcraftLightPalette } from "./theme/stackcraftPalette.js";
26
26
  import { toolkitComponents } from "./theme/toolkitComponents.js";
27
27
  import { mergeComponents } from "./theme/mergeComponents.js";
@@ -205,6 +205,7 @@ export {
205
205
  MAIN_CONTENT_ID,
206
206
  MENU_POSITION,
207
207
  MINIMAL_BACKGROUND,
208
+ MINIMAL_TONES,
208
209
  MIN_CONTRAST,
209
210
  default67 as MessageList,
210
211
  default68 as MessageView,
@@ -2,11 +2,23 @@ import { paletteOf } from "./paletteOf.js";
2
2
  import { textSizeOf } from "../appleTracking.js";
3
3
  import { accentTextStylesOf } from "../glassSurface.js";
4
4
  import { lightDarkStylesOf } from "../lightDarkStyles.js";
5
+ const MINIMAL_TONES = Object.freeze({
6
+ light: Object.freeze({ default: "#F2F2F7", paper: "#FFFFFF", fill: "rgba(118, 118, 128, 0.12)", floating: "#E5E5EA" }),
7
+ dark: Object.freeze({ default: "#000000", paper: "#1C1C1E", fill: "rgba(118, 118, 128, 0.24)", floating: "#2C2C2E" })
8
+ });
5
9
  const MINIMAL_BACKGROUND = Object.freeze({
6
- light: { default: "#F2F2F7", paper: "#FFFFFF" },
7
- dark: { default: "#000000", paper: "#1C1C1E" }
10
+ light: { default: MINIMAL_TONES.light.default, paper: MINIMAL_TONES.light.paper },
11
+ dark: { default: MINIMAL_TONES.dark.default, paper: MINIMAL_TONES.dark.paper }
8
12
  });
9
- const TONAL_FILL = Object.freeze({ light: "rgba(118, 118, 128, 0.12)", dark: "rgba(118, 118, 128, 0.24)" });
13
+ function minimalTonesOf(projectTones = {}) {
14
+ return {
15
+ light: { ...MINIMAL_TONES.light, ...projectTones.light },
16
+ dark: { ...MINIMAL_TONES.dark, ...projectTones.dark }
17
+ };
18
+ }
19
+ function tonesOf(theme) {
20
+ return theme.toolkit?.minimalTones ?? MINIMAL_TONES;
21
+ }
10
22
  const TINT_PERCENT = Object.freeze({ rest: 14, hover: 22, ring: 45 });
11
23
  const RADIUS_PIXELS = Object.freeze({ card: 16, control: 10, group: 12, segment: 9 });
12
24
  const SMALL_TITLE_PIXELS = 13;
@@ -16,14 +28,15 @@ function tintOf(theme, colorName = "primary", percent = TINT_PERCENT.rest) {
16
28
  return `color-mix(in srgb, ${color} ${percent}%, transparent)`;
17
29
  }
18
30
  function tonalFillOf(theme) {
19
- return lightDarkStylesOf(theme, { backgroundColor: TONAL_FILL.light }, { backgroundColor: TONAL_FILL.dark });
31
+ const tones = tonesOf(theme);
32
+ return lightDarkStylesOf(theme, { backgroundColor: tones.light.fill }, { backgroundColor: tones.dark.fill });
20
33
  }
21
34
  function selectedTintOf(theme) {
22
35
  return { backgroundColor: tintOf(theme), ...accentTextStylesOf(theme) };
23
36
  }
24
- const FLOATING_TONE = Object.freeze({ light: "#E5E5EA", dark: "#2C2C2E" });
25
37
  function minimalFloatingStylesOf(theme) {
26
- return lightDarkStylesOf(theme, { backgroundColor: FLOATING_TONE.light }, { backgroundColor: FLOATING_TONE.dark });
38
+ const tones = tonesOf(theme);
39
+ return lightDarkStylesOf(theme, { backgroundColor: tones.light.floating }, { backgroundColor: tones.dark.floating });
27
40
  }
28
41
  function minimalComponents() {
29
42
  return {
@@ -144,7 +157,9 @@ function minimalComponents() {
144
157
  }
145
158
  export {
146
159
  MINIMAL_BACKGROUND,
160
+ MINIMAL_TONES,
147
161
  minimalComponents,
148
- minimalFloatingStylesOf
162
+ minimalFloatingStylesOf,
163
+ minimalTonesOf
149
164
  };
150
165
  //# sourceMappingURL=minimalComponents.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"minimalComponents.js","sources":["../../../src/theme/components/minimalComponents.js"],"sourcesContent":["// El estilo minimalista (createToolkitTheme({look: 'minimal'})): plano y tonal, como pidió el autor («casi solo colores, sin\n// bordes, que el mismo color diga dónde están las superficies»; su referencia: BELOW y Samurai Jack, formas de bloques de\n// color sin contorno y una sola luz de acento).\n//\n// Las reglas:\n// - sin bordes ni sombras: las superficies se separan por su tono, con los grises de Apple (el fondo agrupado gris y las\n// tarjetas un escalón arriba, MINIMAL_BACKGROUND; los campos, el gris de relleno, TONAL_FILL);\n// - un solo color de acento: el botón principal, lo elegido (un tinte suave de su color, sin marco) y las ligas; lo demás\n// neutro. El botón con borde y la etiqueta con borde pasan a «tonales»: el tinte de su color, sin la raya;\n// - sin vidrio ni degradados: superficies sólidas.\n// Va encima de los ajustes del framework (toolkitComponents) y el proyecto puede sumar los suyos encima.\n//\n// Funciones puras, sin React: function (regla de la casa).\nimport {paletteOf} from '@/theme/components/paletteOf.js';\nimport {textSizeOf} from '@/theme/appleTracking.js';\nimport {accentTextStylesOf} from '@/theme/glassSurface.js';\nimport {lightDarkStylesOf} from '@/theme/lightDarkStyles.js';\n\n/** Los fondos del minimalista: el gris agrupado de Apple y la tarjeta un escalón arriba, en claro y en oscuro. */\nexport const MINIMAL_BACKGROUND = Object.freeze({\n light: {default: '#F2F2F7', paper: '#FFFFFF'},\n dark: {default: '#000000', paper: '#1C1C1E'},\n});\n\n// el gris de relleno de Apple para campos y grupos (más claro que el fondo en oscuro)\nconst TONAL_FILL = Object.freeze({light: 'rgba(118, 118, 128, 0.12)', dark: 'rgba(118, 118, 128, 0.24)'});\n// el tinte de lo elegido y de los controles tonales (por ciento de su color) y al pasar el cursor\nconst TINT_PERCENT = Object.freeze({rest: 14, hover: 22, ring: 45});\n// las esquinas: tarjetas y controles (px)\nconst RADIUS_PIXELS = Object.freeze({card: 16, control: 10, group: 12, segment: 9});\n// los títulos chicos (overline), como se escriben (px)\nconst SMALL_TITLE_PIXELS = 13;\n\n/**\n * El tinte de un color del tema (lo elegido, un botón tonal).\n *\n * @param {object} theme\n * @param {string} [colorName]\n * @param {number} [percent]\n * @returns {string}\n */\nfunction tintOf(theme, colorName = 'primary', percent = TINT_PERCENT.rest) {\n const palette = paletteOf(theme);\n const color = (palette[colorName] ?? palette.primary).main;\n return `color-mix(in srgb, ${color} ${percent}%, transparent)`;\n}\n\n/**\n * El relleno gris de un campo o de un grupo, en claro y en oscuro.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction tonalFillOf(theme) {\n return lightDarkStylesOf(theme, {backgroundColor: TONAL_FILL.light}, {backgroundColor: TONAL_FILL.dark});\n}\n\n/**\n * Lo elegido: el tinte suave del acento y su letra legible, sin marco ni gota.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction selectedTintOf(theme) {\n return {backgroundColor: tintOf(theme), ...accentTextStylesOf(theme)};\n}\n\n// lo que flota sobre el contenido en el minimalista (la barra de pestañas del teléfono, el aviso de versión nueva): el gris\n// 5 de Apple, un escalón más oscuro que las tarjetas. Del color de las tarjetas «se perdía» sobre ellas (lo dijo el autor\n// de la primera barra de abajo del minimalista); así se distingue sin borde ni sombra, sobre tarjetas y sobre el fondo\nconst FLOATING_TONE = Object.freeze({light: '#E5E5EA', dark: '#2C2C2E'});\n\n/**\n * La superficie de lo que flota en el minimalista, sólida, en claro y en oscuro.\n *\n * @param {object} theme\n * @returns {object}\n */\nexport function minimalFloatingStylesOf(theme) {\n return lightDarkStylesOf(theme, {backgroundColor: FLOATING_TONE.light}, {backgroundColor: FLOATING_TONE.dark});\n}\n\n/**\n * @returns {object} el `components` del tema de MUI para el estilo minimalista\n */\nexport function minimalComponents() {\n return {\n MuiPaper: {\n defaultProps: {elevation: 0},\n styleOverrides: {\n root: {backgroundImage: 'none', boxShadow: 'none'},\n outlined: {border: 0},\n rounded: {borderRadius: RADIUS_PIXELS.card},\n },\n },\n MuiCard: {defaultProps: {elevation: 0}},\n // la barra del mismo tono que el fondo: sin raya ni sombra, solo su contenido\n MuiAppBar: {\n defaultProps: {elevation: 0, color: 'inherit'},\n styleOverrides: {\n root: ({theme}) => ({backgroundColor: paletteOf(theme).background.default, color: paletteOf(theme).text.primary, boxShadow: 'none', borderBottom: 0}),\n },\n },\n // el menú lateral también del tono del fondo, sin raya: lo separa el espacio, no una línea\n MuiDrawer: {\n styleOverrides: {\n paper: ({theme}) => ({backgroundColor: paletteOf(theme).background.default, borderRight: 0, backgroundImage: 'none'}),\n },\n },\n MuiButton: {\n defaultProps: {disableElevation: true},\n styleOverrides: {\n root: {borderRadius: RADIUS_PIXELS.control, boxShadow: 'none'},\n // el de borde es «tonal»: el tinte de su color, sin la raya\n outlined: ({ownerState, theme}) => ({\n border: 0,\n backgroundColor: tintOf(theme, ownerState.color),\n '&:hover': {border: 0, backgroundColor: tintOf(theme, ownerState.color, TINT_PERCENT.hover)},\n }),\n },\n },\n MuiButtonGroup: {defaultProps: {disableElevation: true}},\n MuiOutlinedInput: {\n styleOverrides: {\n root: ({theme}) => ({\n ...tonalFillOf(theme),\n borderRadius: RADIUS_PIXELS.control,\n '&.Mui-focused': {outline: `2px solid ${tintOf(theme, 'primary', TINT_PERCENT.ring)}`},\n '&.Mui-error': {outline: `2px solid ${tintOf(theme, 'error', TINT_PERCENT.ring)}`},\n }),\n notchedOutline: {border: 0},\n },\n },\n MuiFilledInput: {\n defaultProps: {disableUnderline: true},\n styleOverrides: {root: ({theme}) => ({...tonalFillOf(theme), borderRadius: RADIUS_PIXELS.control})},\n },\n // la etiqueta con borde también es tonal: el tinte de su color (o el gris si no lleva color)\n MuiChip: {\n styleOverrides: {\n outlined: ({ownerState, theme}) => ({\n border: 0,\n ...(ownerState.color && ownerState.color !== 'default' ? {backgroundColor: tintOf(theme, ownerState.color)} : tonalFillOf(theme)),\n }),\n },\n },\n MuiListItemButton: {\n styleOverrides: {\n root: ({theme}) => ({borderRadius: RADIUS_PIXELS.control, '&.Mui-selected, &.Mui-selected:hover': selectedTintOf(theme)}),\n },\n },\n MuiMenuItem: {\n styleOverrides: {\n root: ({theme}) => ({'&.Mui-selected, &.Mui-selected:hover': selectedTintOf(theme)}),\n },\n },\n // el grupo de botones (el control segmentado): una tira gris y lo elegido en blanco (claro) o un escalón arriba (oscuro)\n MuiToggleButtonGroup: {\n styleOverrides: {\n root: ({theme}) => ({...tonalFillOf(theme), border: 0, borderRadius: RADIUS_PIXELS.group, padding: 3, gap: 3}),\n grouped: {border: 0, borderRadius: `${RADIUS_PIXELS.segment}px !important`},\n },\n },\n MuiToggleButton: {\n styleOverrides: {\n root: ({theme}) => ({\n border: 0,\n ...lightDarkStylesOf(theme,\n {'&.Mui-selected, &.Mui-selected:hover': {backgroundColor: paletteOf(theme).background.paper, color: paletteOf(theme).text.primary}},\n {'&.Mui-selected, &.Mui-selected:hover': {backgroundColor: 'rgba(118, 118, 128, 0.36)'}}),\n }),\n },\n },\n MuiTab: {\n styleOverrides: {\n root: ({theme}) => ({'&.Mui-selected': accentTextStylesOf(theme)}),\n },\n },\n // las tablas sin rayas entre renglones: el encabezado se distingue por su tono\n MuiTableCell: {\n styleOverrides: {\n root: {borderBottom: 0},\n head: ({theme}) => ({...tonalFillOf(theme), fontWeight: 600}),\n },\n },\n MuiDataGrid: {\n styleOverrides: {\n root: {border: 0, '--DataGrid-rowBorderColor': 'transparent'},\n columnHeaders: ({theme}) => tonalFillOf(theme),\n },\n },\n MuiAlert: {styleOverrides: {root: {border: 0}}},\n // los títulos chicos como se escriben (Apple ya no los pone en mayúsculas), con el espaciado de su tamaño\n MuiTypography: {\n styleOverrides: {\n overline: {textTransform: 'none', fontWeight: 600, ...textSizeOf(SMALL_TITLE_PIXELS)},\n },\n },\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"minimalComponents.js","sources":["../../../src/theme/components/minimalComponents.js"],"sourcesContent":["// El estilo minimalista (createToolkitTheme({look: 'minimal'})): plano y tonal, como pidió el autor («casi solo colores, sin\n// bordes, que el mismo color diga dónde están las superficies»; su referencia: BELOW y Samurai Jack, formas de bloques de\n// color sin contorno y una sola luz de acento).\n//\n// Las reglas:\n// - sin bordes ni sombras: las superficies se separan por su tono, por omisión con los grises de Apple (MINIMAL_TONES: el\n// fondo agrupado gris y las tarjetas un escalón arriba; los campos, el gris de relleno; lo que flota, un gris más). Cada\n// proyecto puede pasar los suyos (createToolkitTheme minimalTones) y el minimalista se pinta con su marca;\n// - un solo color de acento: el botón principal, lo elegido (un tinte suave de su color, sin marco) y las ligas; lo demás\n// neutro. El botón con borde y la etiqueta con borde pasan a «tonales»: el tinte de su color, sin la raya;\n// - sin vidrio ni degradados: superficies sólidas.\n// Va encima de los ajustes del framework (toolkitComponents) y el proyecto puede sumar los suyos encima.\n//\n// Funciones puras, sin React: function (regla de la casa).\nimport {paletteOf} from '@/theme/components/paletteOf.js';\nimport {textSizeOf} from '@/theme/appleTracking.js';\nimport {accentTextStylesOf} from '@/theme/glassSurface.js';\nimport {lightDarkStylesOf} from '@/theme/lightDarkStyles.js';\n\n/**\n * Los tonos del minimalista por omisión, los grises de Apple, en claro y en oscuro:\n * - default: el fondo de la página (el gris agrupado);\n * - paper: las tarjetas, un escalón arriba;\n * - fill: el relleno de campos, grupos y botones sin color (más claro que el fondo en oscuro);\n * - floating: lo que flota sobre el contenido (la barra de pestañas del teléfono, el aviso de versión nueva), un escalón\n * más oscuro que las tarjetas. Del color de las tarjetas «se perdía» sobre ellas (lo dijo el autor de la primera barra\n * de abajo del minimalista); así se distingue sin borde ni sombra, sobre tarjetas y sobre el fondo.\n */\nexport const MINIMAL_TONES = Object.freeze({\n light: Object.freeze({default: '#F2F2F7', paper: '#FFFFFF', fill: 'rgba(118, 118, 128, 0.12)', floating: '#E5E5EA'}),\n dark: Object.freeze({default: '#000000', paper: '#1C1C1E', fill: 'rgba(118, 118, 128, 0.24)', floating: '#2C2C2E'}),\n});\n\n/** Los fondos del minimalista por omisión (los de MINIMAL_TONES): el gris agrupado de Apple y la tarjeta un escalón arriba. */\nexport const MINIMAL_BACKGROUND = Object.freeze({\n light: {default: MINIMAL_TONES.light.default, paper: MINIMAL_TONES.light.paper},\n dark: {default: MINIMAL_TONES.dark.default, paper: MINIMAL_TONES.dark.paper},\n});\n\n/**\n * Los tonos del minimalista con los del proyecto encima: lo que el proyecto no trae se queda con el gris de Apple.\n *\n * @param {{light?: object, dark?: object}} [projectTones] cualquiera de default, paper, fill y floating por modo\n * @returns {{light: {default: string, paper: string, fill: string, floating: string}, dark: {default: string, paper: string, fill: string, floating: string}}}\n */\nexport function minimalTonesOf(projectTones = {}) {\n return {\n light: {...MINIMAL_TONES.light, ...projectTones.light},\n dark: {...MINIMAL_TONES.dark, ...projectTones.dark},\n };\n}\n\n/** Los tonos con que se armó el tema (createToolkitTheme los guarda); sin ellos, los de Apple. */\nfunction tonesOf(theme) {\n return theme.toolkit?.minimalTones ?? MINIMAL_TONES;\n}\n// el tinte de lo elegido y de los controles tonales (por ciento de su color) y al pasar el cursor\nconst TINT_PERCENT = Object.freeze({rest: 14, hover: 22, ring: 45});\n// las esquinas: tarjetas y controles (px)\nconst RADIUS_PIXELS = Object.freeze({card: 16, control: 10, group: 12, segment: 9});\n// los títulos chicos (overline), como se escriben (px)\nconst SMALL_TITLE_PIXELS = 13;\n\n/**\n * El tinte de un color del tema (lo elegido, un botón tonal).\n *\n * @param {object} theme\n * @param {string} [colorName]\n * @param {number} [percent]\n * @returns {string}\n */\nfunction tintOf(theme, colorName = 'primary', percent = TINT_PERCENT.rest) {\n const palette = paletteOf(theme);\n const color = (palette[colorName] ?? palette.primary).main;\n return `color-mix(in srgb, ${color} ${percent}%, transparent)`;\n}\n\n/**\n * El relleno gris de un campo o de un grupo, en claro y en oscuro.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction tonalFillOf(theme) {\n const tones = tonesOf(theme);\n return lightDarkStylesOf(theme, {backgroundColor: tones.light.fill}, {backgroundColor: tones.dark.fill});\n}\n\n/**\n * Lo elegido: el tinte suave del acento y su letra legible, sin marco ni gota.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction selectedTintOf(theme) {\n return {backgroundColor: tintOf(theme), ...accentTextStylesOf(theme)};\n}\n\n/**\n * La superficie de lo que flota en el minimalista, sólida, en claro y en oscuro (el tono floating; ver MINIMAL_TONES).\n *\n * @param {object} theme\n * @returns {object}\n */\nexport function minimalFloatingStylesOf(theme) {\n const tones = tonesOf(theme);\n return lightDarkStylesOf(theme, {backgroundColor: tones.light.floating}, {backgroundColor: tones.dark.floating});\n}\n\n/**\n * @returns {object} el `components` del tema de MUI para el estilo minimalista\n */\nexport function minimalComponents() {\n return {\n MuiPaper: {\n defaultProps: {elevation: 0},\n styleOverrides: {\n root: {backgroundImage: 'none', boxShadow: 'none'},\n outlined: {border: 0},\n rounded: {borderRadius: RADIUS_PIXELS.card},\n },\n },\n MuiCard: {defaultProps: {elevation: 0}},\n // la barra del mismo tono que el fondo: sin raya ni sombra, solo su contenido\n MuiAppBar: {\n defaultProps: {elevation: 0, color: 'inherit'},\n styleOverrides: {\n root: ({theme}) => ({backgroundColor: paletteOf(theme).background.default, color: paletteOf(theme).text.primary, boxShadow: 'none', borderBottom: 0}),\n },\n },\n // el menú lateral también del tono del fondo, sin raya: lo separa el espacio, no una línea\n MuiDrawer: {\n styleOverrides: {\n paper: ({theme}) => ({backgroundColor: paletteOf(theme).background.default, borderRight: 0, backgroundImage: 'none'}),\n },\n },\n MuiButton: {\n defaultProps: {disableElevation: true},\n styleOverrides: {\n root: {borderRadius: RADIUS_PIXELS.control, boxShadow: 'none'},\n // el de borde es «tonal»: el tinte de su color, sin la raya\n outlined: ({ownerState, theme}) => ({\n border: 0,\n backgroundColor: tintOf(theme, ownerState.color),\n '&:hover': {border: 0, backgroundColor: tintOf(theme, ownerState.color, TINT_PERCENT.hover)},\n }),\n },\n },\n MuiButtonGroup: {defaultProps: {disableElevation: true}},\n MuiOutlinedInput: {\n styleOverrides: {\n root: ({theme}) => ({\n ...tonalFillOf(theme),\n borderRadius: RADIUS_PIXELS.control,\n '&.Mui-focused': {outline: `2px solid ${tintOf(theme, 'primary', TINT_PERCENT.ring)}`},\n '&.Mui-error': {outline: `2px solid ${tintOf(theme, 'error', TINT_PERCENT.ring)}`},\n }),\n notchedOutline: {border: 0},\n },\n },\n MuiFilledInput: {\n defaultProps: {disableUnderline: true},\n styleOverrides: {root: ({theme}) => ({...tonalFillOf(theme), borderRadius: RADIUS_PIXELS.control})},\n },\n // la etiqueta con borde también es tonal: el tinte de su color (o el gris si no lleva color)\n MuiChip: {\n styleOverrides: {\n outlined: ({ownerState, theme}) => ({\n border: 0,\n ...(ownerState.color && ownerState.color !== 'default' ? {backgroundColor: tintOf(theme, ownerState.color)} : tonalFillOf(theme)),\n }),\n },\n },\n MuiListItemButton: {\n styleOverrides: {\n root: ({theme}) => ({borderRadius: RADIUS_PIXELS.control, '&.Mui-selected, &.Mui-selected:hover': selectedTintOf(theme)}),\n },\n },\n MuiMenuItem: {\n styleOverrides: {\n root: ({theme}) => ({'&.Mui-selected, &.Mui-selected:hover': selectedTintOf(theme)}),\n },\n },\n // el grupo de botones (el control segmentado): una tira gris y lo elegido en blanco (claro) o un escalón arriba (oscuro)\n MuiToggleButtonGroup: {\n styleOverrides: {\n root: ({theme}) => ({...tonalFillOf(theme), border: 0, borderRadius: RADIUS_PIXELS.group, padding: 3, gap: 3}),\n grouped: {border: 0, borderRadius: `${RADIUS_PIXELS.segment}px !important`},\n },\n },\n MuiToggleButton: {\n styleOverrides: {\n root: ({theme}) => ({\n border: 0,\n ...lightDarkStylesOf(theme,\n {'&.Mui-selected, &.Mui-selected:hover': {backgroundColor: paletteOf(theme).background.paper, color: paletteOf(theme).text.primary}},\n {'&.Mui-selected, &.Mui-selected:hover': {backgroundColor: 'rgba(118, 118, 128, 0.36)'}}),\n }),\n },\n },\n MuiTab: {\n styleOverrides: {\n root: ({theme}) => ({'&.Mui-selected': accentTextStylesOf(theme)}),\n },\n },\n // las tablas sin rayas entre renglones: el encabezado se distingue por su tono\n MuiTableCell: {\n styleOverrides: {\n root: {borderBottom: 0},\n head: ({theme}) => ({...tonalFillOf(theme), fontWeight: 600}),\n },\n },\n MuiDataGrid: {\n styleOverrides: {\n root: {border: 0, '--DataGrid-rowBorderColor': 'transparent'},\n columnHeaders: ({theme}) => tonalFillOf(theme),\n },\n },\n MuiAlert: {styleOverrides: {root: {border: 0}}},\n // los títulos chicos como se escriben (Apple ya no los pone en mayúsculas), con el espaciado de su tamaño\n MuiTypography: {\n styleOverrides: {\n overline: {textTransform: 'none', fontWeight: 600, ...textSizeOf(SMALL_TITLE_PIXELS)},\n },\n },\n };\n}\n"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import { mergeComponents } from "./mergeComponents.js";
6
6
  import { stackcraftDarkPalette, stackcraftLightPalette } from "./stackcraftPalette.js";
7
7
  import { trackingOf } from "./appleTracking.js";
8
8
  import { toolkitComponents } from "./toolkitComponents.js";
9
- import { minimalComponents, MINIMAL_BACKGROUND } from "./components/minimalComponents.js";
9
+ import { minimalComponents, minimalTonesOf } from "./components/minimalComponents.js";
10
10
  import { createLogger } from "../observability/logger.js";
11
11
  const log = createLogger("theme");
12
12
  let hasWarnedAboutGlassSurfaces = false;
@@ -38,6 +38,7 @@ function createToolkitTheme({
38
38
  glass = false,
39
39
  look = THEME_LOOK.standard,
40
40
  bar = TOP_BAR.capsules,
41
+ minimalTones = {},
41
42
  components = {},
42
43
  overrides = {}
43
44
  } = {}) {
@@ -47,9 +48,10 @@ function createToolkitTheme({
47
48
  const isMinimal = look === THEME_LOOK.minimal;
48
49
  const glassSettings = isMinimal ? null : glassSettingsOf(glass);
49
50
  const frameworkComponents = isMinimal ? mergeComponents(toolkitComponents(), minimalComponents()) : glassSettings ? mergeComponents(toolkitComponents(), glassComponents({ surfaces: glassSettings.surfaces })) : toolkitComponents();
51
+ const tones = isMinimal ? minimalTonesOf(minimalTones) : null;
50
52
  const schemes = isMinimal ? Object.fromEntries(Object.entries(colorSchemes).map(([mode, scheme]) => [mode, {
51
53
  ...scheme,
52
- palette: { ...scheme.palette, background: MINIMAL_BACKGROUND[mode] ?? scheme.palette?.background }
54
+ palette: { ...scheme.palette, background: tones[mode] ? { default: tones[mode].default, paper: tones[mode].paper } : scheme.palette?.background }
53
55
  }])) : colorSchemes;
54
56
  const baseTheme = createTheme({
55
57
  cssVariables: { colorSchemeSelector },
@@ -87,7 +89,8 @@ function createToolkitTheme({
87
89
  components: mergeComponents(frameworkComponents, components),
88
90
  // sin sombras en el minimalista: lo plano es la idea
89
91
  ...isMinimal && { shadows: Array(SHADOW_LEVELS).fill("none") },
90
- toolkit: { glass: glassSettings, look, bar },
92
+ // minimalTones: los tonos con que se pintan los rellenos y lo que flota (minimalComponents los lee del tema)
93
+ toolkit: { glass: glassSettings, look, bar, minimalTones: tones },
91
94
  ...overrides
92
95
  });
93
96
  return responsiveFontSizes(baseTheme);
@@ -1 +1 @@
1
- {"version":3,"file":"createToolkitTheme.js","sources":["../../src/theme/createToolkitTheme.js"],"sourcesContent":["// El tema del framework: el estilo de Stackcraft (del tema de walk-ot) con claro y oscuro. Es opcional: ToolkitProvider\n// funciona con cualquier tema de MUI.\n//\n// const theme = createToolkitTheme(); // los colores de Stackcraft\n// const theme = createToolkitTheme({glass: true}); // con vidrio líquido en lo que flota\n// const theme = createToolkitTheme({glass: {opacity: 0.7}}); // con vidrio más transparente (por omisión 0.8)\n// const theme = createToolkitTheme({glass: {surfaces: true}}); // también las tarjetas del contenido (con advertencia)\n// const theme = createToolkitTheme({glass: true, bar: TOP_BAR.band}); // la barra de arriba en franja (por omisión, cápsulas)\n// const theme = createToolkitTheme({colorSchemes: {light: {palette: {primary: {main: '#0B5FFF'}}}, dark: {...}}});\n//\n// Lo que trae, con su porqué:\n// - variables CSS y los dos modos: ColorSchemeToggle cambia de modo sin volver a pintar, y las gráficas leen sus colores\n// del tema (theme.vars): con variables cambian solas al cambiar de modo, sin ellas se quedarían con las del arranque.\n// - colorSchemeSelector 'class': el modo lo elige la persona con el botón (con 'media' solo mandaría el sistema\n// operativo y el botón no haría nada). Con Next.js va con <InitColorSchemeScript attribute=\"class\" />.\n// - letra base de 16 px: con menos, el iPhone hace zoom al entrar a un campo. body1 16 px y body2 15 px en el teléfono;\n// responsiveFontSizes los ajusta por ancho de pantalla.\n// - transiciones de 220 ms, iguales al abrir y al cerrar: más ágiles que las de Material (300 ms) y sin el desfase de\n// 30 ms entre lo que solo conoce una transición (la barra) y lo que conoce dos (el menú lateral).\n// - esquinas de 8 px y los ajustes de componentes de toolkitComponents().\n// - glass: el vidrio líquido en lo que flota y en los controles (glassSurface.js explica dónde y por qué). Queda anotado\n// en theme.toolkit.glass para que los componentes del framework que flotan (el marco, los avisos) lo sepan sin otra prop.\n// - components: los ajustes propios del proyecto se SUMAN a los del framework (mergeComponents), no los borran.\n//\n// Funciones puras, sin React: function (regla de la casa).\nimport {createTheme, responsiveFontSizes} from '@mui/material/styles';\n\nimport {glassComponents} from '@/theme/components/glassComponents.js';\nimport {GLASS_OPACITY} from '@/theme/glassSurface.js';\nimport {mergeComponents} from '@/theme/mergeComponents.js';\nimport {stackcraftDarkPalette, stackcraftLightPalette} from '@/theme/stackcraftPalette.js';\nimport {trackingOf} from '@/theme/appleTracking.js';\nimport {toolkitComponents} from '@/theme/toolkitComponents.js';\nimport {MINIMAL_BACKGROUND, minimalComponents} from '@/theme/components/minimalComponents.js';\nimport {createLogger} from '@/observability/logger.js';\n\nconst log = createLogger('theme');\n// el aviso de las tarjetas de vidrio sale una vez por pestaña: el tema se vuelve a armar cada vez que cambia algo (un\n// configurador de tema lo arma en cada clic) y la consola se llenaba del mismo aviso\nlet hasWarnedAboutGlassSurfaces = false;\n\nconst SYSTEM_FONT_FAMILY = 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif';\nconst CORNER_RADIUS_PIXELS = 8;\n// cuántos niveles de sombra trae el tema de MUI (del 0 al 24)\nconst SHADOW_LEVELS = 25;\n\n/** El estilo del tema: el de Stackcraft (con vidrio o sin él) o el minimalista, plano y tonal. */\nexport const THEME_LOOK = Object.freeze({standard: 'standard', minimal: 'minimal'});\n\n/**\n * La barra de arriba, con vidrio y con el minimalista: por omisión como las ventanas de macOS Tahoe, sin franja (el nombre\n * y los botones en cápsulas por grupo; lo eligió el autor al verlas), o la franja de lado a lado. Con vidrio las cápsulas\n * son de vidrio y el contenido pasa por debajo desenfocado; con el minimalista son bloques del tono de las tarjetas sobre\n * el color del fondo (AppLayout). El estilo de Stackcraft sin vidrio se queda con su barra de siempre.\n */\nexport const TOP_BAR = Object.freeze({band: 'band', capsules: 'capsules'});\n\n/**\n * Lo que pidió el proyecto del vidrio, ya revisado: false (sin vidrio) o {opacity, surfaces}.\n *\n * @param {boolean|{opacity?: number, surfaces?: boolean}} glass\n * @returns {false|{opacity: number, surfaces: boolean}}\n */\nfunction glassSettingsOf(glass) {\n if (!glass) {\n return false;\n }\n const requested = glass === true ? {} : glass;\n const opacity = requested.opacity ?? GLASS_OPACITY;\n // un 80 en lugar de 0.8 daría un color inválido y la barra saldría sin fondo, sin ningún aviso\n if (typeof opacity !== 'number' || opacity < 0 || opacity > 1) {\n throw new RangeError(`createToolkitTheme: glass.opacity va de 0 a 1 (llegó ${opacity}).`);\n }\n const surfaces = Boolean(requested.surfaces);\n // se permite, pero con advertencia: la guía de Apple pide el contenido sin vidrio y cada tarjeta desenfoca lo de atrás\n if (surfaces && !hasWarnedAboutGlassSurfaces) {\n hasWarnedAboutGlassSurfaces = true;\n log.warn('glass.surfaces pone vidrio también en el contenido (tarjetas, avisos, tabla): pesa más en equipos modestos '\n + 'y la guía de Apple no lo recomienda («no use Liquid Glass en la capa del contenido»). Úselo en una portada o una '\n + 'demostración, no en pantallas de trabajo.');\n }\n return {opacity, surfaces};\n}\n\n/**\n * @param {object} [options]\n * @param {{light?: object|boolean, dark?: object|boolean}} [options.colorSchemes] los colores de cada modo; por omisión los de\n * Stackcraft; true: los de MUI tal cual\n * @param {'class'|'data'|'media'|string} [options.colorSchemeSelector] cómo se elige el modo; por omisión 'class'\n * @param {string} [options.fontFamily] por omisión la letra del sistema\n * @param {boolean|{opacity?: number, surfaces?: boolean}} [options.glass] vidrio líquido en lo que flota y en los\n * controles; por omisión no. Con {opacity} se elige qué tan opaco (0 a 1; por omisión GLASS_OPACITY, 0.6) y con\n * {surfaces: true} también las tarjetas del contenido (por omisión sólidas, como pide la guía; avisa en consola)\n * @param {'standard'|'minimal'} [options.look] el estilo (THEME_LOOK): el de Stackcraft (por omisión) o el minimalista,\n * plano y tonal (sin bordes ni sombras: las superficies se separan por su tono; sin vidrio aunque se pida)\n * @param {'capsules'|'band'} [options.bar] la barra de arriba con vidrio o con el minimalista (TOP_BAR): por omisión en\n * cápsulas; 'band' la franja de lado a lado\n * @param {object} [options.components] ajustes propios de componentes (se suman; en el mismo estilo ganan los del proyecto)\n * @param {object} [options.overrides] cualquier otra cosa de createTheme (breakpoints, spacing…)\n * @returns {object} el tema de MUI\n */\nexport function createToolkitTheme({\n colorSchemes = {light: {palette: stackcraftLightPalette}, dark: {palette: stackcraftDarkPalette}},\n colorSchemeSelector = 'class',\n fontFamily = SYSTEM_FONT_FAMILY,\n glass = false,\n look = THEME_LOOK.standard,\n bar = TOP_BAR.capsules,\n components = {},\n overrides = {},\n} = {}) {\n // un nombre mal escrito dejaría la franja sin avisar: mejor que truene al armar el tema\n if (!Object.values(TOP_BAR).includes(bar)) {\n throw new RangeError(`createToolkitTheme: bar es '${TOP_BAR.capsules}' o '${TOP_BAR.band}' (llegó ${bar}).`);\n }\n const isMinimal = look === THEME_LOOK.minimal;\n // el minimalista es sólido: sin vidrio aunque se pida\n const glassSettings = isMinimal ? null : glassSettingsOf(glass);\n const frameworkComponents = isMinimal\n ? mergeComponents(toolkitComponents(), minimalComponents())\n : (glassSettings ? mergeComponents(toolkitComponents(), glassComponents({surfaces: glassSettings.surfaces})) : toolkitComponents());\n // el minimalista separa las superficies por su tono: el fondo gris agrupado y la tarjeta un escalón arriba\n const schemes = isMinimal\n ? Object.fromEntries(Object.entries(colorSchemes).map(([mode, scheme]) => [mode, {\n ...scheme, palette: {...scheme.palette, background: MINIMAL_BACKGROUND[mode] ?? scheme.palette?.background},\n }]))\n : colorSchemes;\n const baseTheme = createTheme({\n cssVariables: {colorSchemeSelector},\n colorSchemes: schemes,\n // el espaciado entre letras (tracking) de la tabla de SF Pro de Apple para cada tamaño (appleTracking.js). MUI\n // trae uno POSITIVO pensado para Roboto (+0.15 px en el texto, +0.4 px en botones y textos chicos) y con la letra del\n // sistema se veía la letra separada (lo reportaron: «kerning»); Apple, de 13 a 22 pt, lo cierra\n typography: {\n fontFamily,\n h1: {letterSpacing: trackingOf(96)},\n h2: {letterSpacing: trackingOf(60)},\n h3: {letterSpacing: trackingOf(48)},\n h4: {letterSpacing: trackingOf(34)},\n h5: {fontWeight: 600, letterSpacing: trackingOf(24)},\n h6: {fontWeight: 600, letterSpacing: trackingOf(20)},\n subtitle1: {letterSpacing: trackingOf(16)},\n subtitle2: {letterSpacing: trackingOf(14)},\n body1: {fontSize: '1rem', letterSpacing: trackingOf(16)},\n body2: {fontSize: '0.9375rem', letterSpacing: trackingOf(15)},\n button: {fontSize: '0.9375rem', textTransform: 'none', fontWeight: 500, letterSpacing: trackingOf(15)},\n caption: {letterSpacing: trackingOf(12)},\n },\n transitions: {\n duration: {\n shortest: 150,\n shorter: 180,\n short: 200,\n standard: 220,\n complex: 280,\n enteringScreen: 220,\n leavingScreen: 220,\n },\n },\n shape: {borderRadius: CORNER_RADIUS_PIXELS},\n components: mergeComponents(frameworkComponents, components),\n // sin sombras en el minimalista: lo plano es la idea\n ...(isMinimal && {shadows: Array(SHADOW_LEVELS).fill('none')}),\n toolkit: {glass: glassSettings, look, bar},\n ...overrides,\n });\n return responsiveFontSizes(baseTheme);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createToolkitTheme.js","sources":["../../src/theme/createToolkitTheme.js"],"sourcesContent":["// El tema del framework: el estilo de Stackcraft (del tema de walk-ot) con claro y oscuro. Es opcional: ToolkitProvider\n// funciona con cualquier tema de MUI.\n//\n// const theme = createToolkitTheme(); // los colores de Stackcraft\n// const theme = createToolkitTheme({glass: true}); // con vidrio líquido en lo que flota\n// const theme = createToolkitTheme({glass: {opacity: 0.7}}); // con vidrio más transparente (por omisión 0.8)\n// const theme = createToolkitTheme({glass: {surfaces: true}}); // también las tarjetas del contenido (con advertencia)\n// const theme = createToolkitTheme({glass: true, bar: TOP_BAR.band}); // la barra de arriba en franja (por omisión, cápsulas)\n// const theme = createToolkitTheme({colorSchemes: {light: {palette: {primary: {main: '#0B5FFF'}}}, dark: {...}}});\n//\n// Lo que trae, con su porqué:\n// - variables CSS y los dos modos: ColorSchemeToggle cambia de modo sin volver a pintar, y las gráficas leen sus colores\n// del tema (theme.vars): con variables cambian solas al cambiar de modo, sin ellas se quedarían con las del arranque.\n// - colorSchemeSelector 'class': el modo lo elige la persona con el botón (con 'media' solo mandaría el sistema\n// operativo y el botón no haría nada). Con Next.js va con <InitColorSchemeScript attribute=\"class\" />.\n// - letra base de 16 px: con menos, el iPhone hace zoom al entrar a un campo. body1 16 px y body2 15 px en el teléfono;\n// responsiveFontSizes los ajusta por ancho de pantalla.\n// - transiciones de 220 ms, iguales al abrir y al cerrar: más ágiles que las de Material (300 ms) y sin el desfase de\n// 30 ms entre lo que solo conoce una transición (la barra) y lo que conoce dos (el menú lateral).\n// - esquinas de 8 px y los ajustes de componentes de toolkitComponents().\n// - glass: el vidrio líquido en lo que flota y en los controles (glassSurface.js explica dónde y por qué). Queda anotado\n// en theme.toolkit.glass para que los componentes del framework que flotan (el marco, los avisos) lo sepan sin otra prop.\n// - components: los ajustes propios del proyecto se SUMAN a los del framework (mergeComponents), no los borran.\n//\n// Funciones puras, sin React: function (regla de la casa).\nimport {createTheme, responsiveFontSizes} from '@mui/material/styles';\n\nimport {glassComponents} from '@/theme/components/glassComponents.js';\nimport {GLASS_OPACITY} from '@/theme/glassSurface.js';\nimport {mergeComponents} from '@/theme/mergeComponents.js';\nimport {stackcraftDarkPalette, stackcraftLightPalette} from '@/theme/stackcraftPalette.js';\nimport {trackingOf} from '@/theme/appleTracking.js';\nimport {toolkitComponents} from '@/theme/toolkitComponents.js';\nimport {minimalComponents, minimalTonesOf} from '@/theme/components/minimalComponents.js';\nimport {createLogger} from '@/observability/logger.js';\n\nconst log = createLogger('theme');\n// el aviso de las tarjetas de vidrio sale una vez por pestaña: el tema se vuelve a armar cada vez que cambia algo (un\n// configurador de tema lo arma en cada clic) y la consola se llenaba del mismo aviso\nlet hasWarnedAboutGlassSurfaces = false;\n\nconst SYSTEM_FONT_FAMILY = 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif';\nconst CORNER_RADIUS_PIXELS = 8;\n// cuántos niveles de sombra trae el tema de MUI (del 0 al 24)\nconst SHADOW_LEVELS = 25;\n\n/** El estilo del tema: el de Stackcraft (con vidrio o sin él) o el minimalista, plano y tonal. */\nexport const THEME_LOOK = Object.freeze({standard: 'standard', minimal: 'minimal'});\n\n/**\n * La barra de arriba, con vidrio y con el minimalista: por omisión como las ventanas de macOS Tahoe, sin franja (el nombre\n * y los botones en cápsulas por grupo; lo eligió el autor al verlas), o la franja de lado a lado. Con vidrio las cápsulas\n * son de vidrio y el contenido pasa por debajo desenfocado; con el minimalista son bloques del tono de las tarjetas sobre\n * el color del fondo (AppLayout). El estilo de Stackcraft sin vidrio se queda con su barra de siempre.\n */\nexport const TOP_BAR = Object.freeze({band: 'band', capsules: 'capsules'});\n\n/**\n * Lo que pidió el proyecto del vidrio, ya revisado: false (sin vidrio) o {opacity, surfaces}.\n *\n * @param {boolean|{opacity?: number, surfaces?: boolean}} glass\n * @returns {false|{opacity: number, surfaces: boolean}}\n */\nfunction glassSettingsOf(glass) {\n if (!glass) {\n return false;\n }\n const requested = glass === true ? {} : glass;\n const opacity = requested.opacity ?? GLASS_OPACITY;\n // un 80 en lugar de 0.8 daría un color inválido y la barra saldría sin fondo, sin ningún aviso\n if (typeof opacity !== 'number' || opacity < 0 || opacity > 1) {\n throw new RangeError(`createToolkitTheme: glass.opacity va de 0 a 1 (llegó ${opacity}).`);\n }\n const surfaces = Boolean(requested.surfaces);\n // se permite, pero con advertencia: la guía de Apple pide el contenido sin vidrio y cada tarjeta desenfoca lo de atrás\n if (surfaces && !hasWarnedAboutGlassSurfaces) {\n hasWarnedAboutGlassSurfaces = true;\n log.warn('glass.surfaces pone vidrio también en el contenido (tarjetas, avisos, tabla): pesa más en equipos modestos '\n + 'y la guía de Apple no lo recomienda («no use Liquid Glass en la capa del contenido»). Úselo en una portada o una '\n + 'demostración, no en pantallas de trabajo.');\n }\n return {opacity, surfaces};\n}\n\n/**\n * @param {object} [options]\n * @param {{light?: object|boolean, dark?: object|boolean}} [options.colorSchemes] los colores de cada modo; por omisión los de\n * Stackcraft; true: los de MUI tal cual\n * @param {'class'|'data'|'media'|string} [options.colorSchemeSelector] cómo se elige el modo; por omisión 'class'\n * @param {string} [options.fontFamily] por omisión la letra del sistema\n * @param {boolean|{opacity?: number, surfaces?: boolean}} [options.glass] vidrio líquido en lo que flota y en los\n * controles; por omisión no. Con {opacity} se elige qué tan opaco (0 a 1; por omisión GLASS_OPACITY, 0.6) y con\n * {surfaces: true} también las tarjetas del contenido (por omisión sólidas, como pide la guía; avisa en consola)\n * @param {'standard'|'minimal'} [options.look] el estilo (THEME_LOOK): el de Stackcraft (por omisión) o el minimalista,\n * plano y tonal (sin bordes ni sombras: las superficies se separan por su tono; sin vidrio aunque se pida)\n * @param {'capsules'|'band'} [options.bar] la barra de arriba con vidrio o con el minimalista (TOP_BAR): por omisión en\n * cápsulas; 'band' la franja de lado a lado\n * @param {{light?: {default?: string, paper?: string, fill?: string, floating?: string}, dark?: {default?: string, paper?: string, fill?: string, floating?: string}}} [options.minimalTones]\n * los tonos del minimalista con los colores de la marca, por modo: default (el fondo de la página), paper (las tarjetas,\n * un escalón arriba), fill (el relleno de campos, grupos y botones sin color) y floating (la barra de pestañas del\n * teléfono y lo que flota). Lo que no se pase se queda con los grises de Apple (MINIMAL_TONES). OJO: con el minimalista\n * el fondo de la página sale de aquí y no de la paleta (sin minimalTones, los grises de Apple aunque la paleta traiga\n * su background)\n * @param {object} [options.components] ajustes propios de componentes (se suman; en el mismo estilo ganan los del proyecto)\n * @param {object} [options.overrides] cualquier otra cosa de createTheme (breakpoints, spacing…)\n * @returns {object} el tema de MUI\n */\nexport function createToolkitTheme({\n colorSchemes = {light: {palette: stackcraftLightPalette}, dark: {palette: stackcraftDarkPalette}},\n colorSchemeSelector = 'class',\n fontFamily = SYSTEM_FONT_FAMILY,\n glass = false,\n look = THEME_LOOK.standard,\n bar = TOP_BAR.capsules,\n minimalTones = {},\n components = {},\n overrides = {},\n} = {}) {\n // un nombre mal escrito dejaría la franja sin avisar: mejor que truene al armar el tema\n if (!Object.values(TOP_BAR).includes(bar)) {\n throw new RangeError(`createToolkitTheme: bar es '${TOP_BAR.capsules}' o '${TOP_BAR.band}' (llegó ${bar}).`);\n }\n const isMinimal = look === THEME_LOOK.minimal;\n // el minimalista es sólido: sin vidrio aunque se pida\n const glassSettings = isMinimal ? null : glassSettingsOf(glass);\n const frameworkComponents = isMinimal\n ? mergeComponents(toolkitComponents(), minimalComponents())\n : (glassSettings ? mergeComponents(toolkitComponents(), glassComponents({surfaces: glassSettings.surfaces})) : toolkitComponents());\n // el minimalista separa las superficies por su tono: el fondo de la página y la tarjeta un escalón arriba (los grises de\n // Apple o los tonos de la marca que pasó el proyecto)\n const tones = isMinimal ? minimalTonesOf(minimalTones) : null;\n const schemes = isMinimal\n ? Object.fromEntries(Object.entries(colorSchemes).map(([mode, scheme]) => [mode, {\n ...scheme,\n palette: {...scheme.palette, background: tones[mode] ? {default: tones[mode].default, paper: tones[mode].paper} : scheme.palette?.background},\n }]))\n : colorSchemes;\n const baseTheme = createTheme({\n cssVariables: {colorSchemeSelector},\n colorSchemes: schemes,\n // el espaciado entre letras (tracking) de la tabla de SF Pro de Apple para cada tamaño (appleTracking.js). MUI\n // trae uno POSITIVO pensado para Roboto (+0.15 px en el texto, +0.4 px en botones y textos chicos) y con la letra del\n // sistema se veía la letra separada (lo reportaron: «kerning»); Apple, de 13 a 22 pt, lo cierra\n typography: {\n fontFamily,\n h1: {letterSpacing: trackingOf(96)},\n h2: {letterSpacing: trackingOf(60)},\n h3: {letterSpacing: trackingOf(48)},\n h4: {letterSpacing: trackingOf(34)},\n h5: {fontWeight: 600, letterSpacing: trackingOf(24)},\n h6: {fontWeight: 600, letterSpacing: trackingOf(20)},\n subtitle1: {letterSpacing: trackingOf(16)},\n subtitle2: {letterSpacing: trackingOf(14)},\n body1: {fontSize: '1rem', letterSpacing: trackingOf(16)},\n body2: {fontSize: '0.9375rem', letterSpacing: trackingOf(15)},\n button: {fontSize: '0.9375rem', textTransform: 'none', fontWeight: 500, letterSpacing: trackingOf(15)},\n caption: {letterSpacing: trackingOf(12)},\n },\n transitions: {\n duration: {\n shortest: 150,\n shorter: 180,\n short: 200,\n standard: 220,\n complex: 280,\n enteringScreen: 220,\n leavingScreen: 220,\n },\n },\n shape: {borderRadius: CORNER_RADIUS_PIXELS},\n components: mergeComponents(frameworkComponents, components),\n // sin sombras en el minimalista: lo plano es la idea\n ...(isMinimal && {shadows: Array(SHADOW_LEVELS).fill('none')}),\n // minimalTones: los tonos con que se pintan los rellenos y lo que flota (minimalComponents los lee del tema)\n toolkit: {glass: glassSettings, look, bar, minimalTones: tones},\n ...overrides,\n });\n return responsiveFontSizes(baseTheme);\n}\n"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@ export { ConfirmDialog, ModalWaiting, NEW_BUILD_NOTICE_VARIANT, NewBuildNotice,
11
11
  export { DEFAULT_FILE_TYPES, DOWNLOAD_STATUS, DownloadManager, UNKNOWN_FILE_TYPE, cancelDownload, clearFinishedDownloads, downloadsMachine, startDownload, useFileTypes, } from './downloads/index.js';
12
12
  export { THEME_LOOK, TOP_BAR, createToolkitTheme } from './theme/createToolkitTheme.js';
13
13
  export { isAndroidDevice } from './theme/androidDevice.js';
14
- export { MINIMAL_BACKGROUND } from './theme/components/minimalComponents.js';
14
+ export { MINIMAL_BACKGROUND, MINIMAL_TONES } from './theme/components/minimalComponents.js';
15
15
  export { STACKCRAFT, stackcraftDarkPalette, stackcraftLightPalette } from './theme/stackcraftPalette.js';
16
16
  export { toolkitComponents } from './theme/toolkitComponents.js';
17
17
  export { mergeComponents } from './theme/mergeComponents.js';
@@ -1,16 +1,62 @@
1
- /** Los fondos del minimalista: el gris agrupado de Apple y la tarjeta un escalón arriba, en claro y en oscuro. */
1
+ /**
2
+ * Los tonos del minimalista por omisión, los grises de Apple, en claro y en oscuro:
3
+ * - default: el fondo de la página (el gris agrupado);
4
+ * - paper: las tarjetas, un escalón arriba;
5
+ * - fill: el relleno de campos, grupos y botones sin color (más claro que el fondo en oscuro);
6
+ * - floating: lo que flota sobre el contenido (la barra de pestañas del teléfono, el aviso de versión nueva), un escalón
7
+ * más oscuro que las tarjetas. Del color de las tarjetas «se perdía» sobre ellas (lo dijo el autor de la primera barra
8
+ * de abajo del minimalista); así se distingue sin borde ni sombra, sobre tarjetas y sobre el fondo.
9
+ */
10
+ export declare const MINIMAL_TONES: Readonly<{
11
+ light: Readonly<{
12
+ default: "#F2F2F7";
13
+ paper: "#FFFFFF";
14
+ fill: "rgba(118, 118, 128, 0.12)";
15
+ floating: "#E5E5EA";
16
+ }>;
17
+ dark: Readonly<{
18
+ default: "#000000";
19
+ paper: "#1C1C1E";
20
+ fill: "rgba(118, 118, 128, 0.24)";
21
+ floating: "#2C2C2E";
22
+ }>;
23
+ }>;
24
+ /** Los fondos del minimalista por omisión (los de MINIMAL_TONES): el gris agrupado de Apple y la tarjeta un escalón arriba. */
2
25
  export declare const MINIMAL_BACKGROUND: Readonly<{
26
+ light: {
27
+ default: "#F2F2F7";
28
+ paper: "#FFFFFF";
29
+ };
30
+ dark: {
31
+ default: "#000000";
32
+ paper: "#1C1C1E";
33
+ };
34
+ }>;
35
+ /**
36
+ * Los tonos del minimalista con los del proyecto encima: lo que el proyecto no trae se queda con el gris de Apple.
37
+ *
38
+ * @param {{light?: object, dark?: object}} [projectTones] cualquiera de default, paper, fill y floating por modo
39
+ * @returns {{light: {default: string, paper: string, fill: string, floating: string}, dark: {default: string, paper: string, fill: string, floating: string}}}
40
+ */
41
+ export declare function minimalTonesOf(projectTones?: {
42
+ light?: object;
43
+ dark?: object;
44
+ }): {
3
45
  light: {
4
46
  default: string;
5
47
  paper: string;
48
+ fill: string;
49
+ floating: string;
6
50
  };
7
51
  dark: {
8
52
  default: string;
9
53
  paper: string;
54
+ fill: string;
55
+ floating: string;
10
56
  };
11
- }>;
57
+ };
12
58
  /**
13
- * La superficie de lo que flota en el minimalista, sólida, en claro y en oscuro.
59
+ * La superficie de lo que flota en el minimalista, sólida, en claro y en oscuro (el tono floating; ver MINIMAL_TONES).
14
60
  *
15
61
  * @param {object} theme
16
62
  * @returns {object}
@@ -26,11 +26,17 @@ export declare const TOP_BAR: Readonly<{
26
26
  * plano y tonal (sin bordes ni sombras: las superficies se separan por su tono; sin vidrio aunque se pida)
27
27
  * @param {'capsules'|'band'} [options.bar] la barra de arriba con vidrio o con el minimalista (TOP_BAR): por omisión en
28
28
  * cápsulas; 'band' la franja de lado a lado
29
+ * @param {{light?: {default?: string, paper?: string, fill?: string, floating?: string}, dark?: {default?: string, paper?: string, fill?: string, floating?: string}}} [options.minimalTones]
30
+ * los tonos del minimalista con los colores de la marca, por modo: default (el fondo de la página), paper (las tarjetas,
31
+ * un escalón arriba), fill (el relleno de campos, grupos y botones sin color) y floating (la barra de pestañas del
32
+ * teléfono y lo que flota). Lo que no se pase se queda con los grises de Apple (MINIMAL_TONES). OJO: con el minimalista
33
+ * el fondo de la página sale de aquí y no de la paleta (sin minimalTones, los grises de Apple aunque la paleta traiga
34
+ * su background)
29
35
  * @param {object} [options.components] ajustes propios de componentes (se suman; en el mismo estilo ganan los del proyecto)
30
36
  * @param {object} [options.overrides] cualquier otra cosa de createTheme (breakpoints, spacing…)
31
37
  * @returns {object} el tema de MUI
32
38
  */
33
- export declare function createToolkitTheme({ colorSchemes, colorSchemeSelector, fontFamily, glass, look, bar, components, overrides, }?: {
39
+ export declare function createToolkitTheme({ colorSchemes, colorSchemeSelector, fontFamily, glass, look, bar, minimalTones, components, overrides, }?: {
34
40
  colorSchemes?: {
35
41
  light?: object | boolean;
36
42
  dark?: object | boolean;
@@ -43,6 +49,20 @@ export declare function createToolkitTheme({ colorSchemes, colorSchemeSelector,
43
49
  };
44
50
  look?: 'standard' | 'minimal';
45
51
  bar?: 'capsules' | 'band';
52
+ minimalTones?: {
53
+ light?: {
54
+ default?: string;
55
+ paper?: string;
56
+ fill?: string;
57
+ floating?: string;
58
+ };
59
+ dark?: {
60
+ default?: string;
61
+ paper?: string;
62
+ fill?: string;
63
+ floating?: string;
64
+ };
65
+ };
46
66
  components?: object;
47
67
  overrides?: object;
48
68
  }): object;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackcraftmx/calcita",
3
- "version": "0.26.0",
3
+ "version": "0.27.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",