@morscherlab/mint-sdk 1.4.0-beta.10 → 1.4.0-beta.12
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/{AlertBox-B2Bgr3ei.js → AlertBox-BdoZqANv.js} +2 -2
- package/dist/{AlertBox-B2Bgr3ei.js.map → AlertBox-BdoZqANv.js.map} +1 -1
- package/dist/{AppSidebar-mvm--GxN.js → AppSidebar-DGK5i-hJ.js} +7 -7
- package/dist/{AppSidebar-mvm--GxN.js.map → AppSidebar-DGK5i-hJ.js.map} +1 -1
- package/dist/{ExperimentPopover-5T1fAq2L.js → ExperimentPopover-CbD7BR_s.js} +2 -2
- package/dist/{ExperimentPopover-5T1fAq2L.js.map → ExperimentPopover-CbD7BR_s.js.map} +1 -1
- package/dist/{ExperimentSelectorModal-65peG4Up.js → ExperimentSelectorModal-BoofZZxF.js} +4 -4
- package/dist/{ExperimentSelectorModal-65peG4Up.js.map → ExperimentSelectorModal-BoofZZxF.js.map} +1 -1
- package/dist/{SegmentedControl-BtnnjWzs.js → SegmentedControl-BkwYOKpG.js} +2 -2
- package/dist/{SegmentedControl-BtnnjWzs.js.map → SegmentedControl-BkwYOKpG.js.map} +1 -1
- package/dist/{SettingsModal-DO3IZ7qz.js → SettingsModal-BXsjIVnm.js} +25 -24
- package/dist/SettingsModal-BXsjIVnm.js.map +1 -0
- package/dist/__tests__/styles/paletteTokens.test.d.ts +1 -0
- package/dist/__tests__/styles/v2AuditRules.test.d.ts +1 -0
- package/dist/components/SmartGroupFieldRecipe.vue.d.ts +1 -1
- package/dist/{controlSchemaModel-B8CTXagP.js → controlSchemaModel-BF5g4wRC.js} +2 -2
- package/dist/{controlSchemaModel-B8CTXagP.js.map → controlSchemaModel-BF5g4wRC.js.map} +1 -1
- package/dist/{data-CgILxDLW.js → data-ihsBd9bs.js} +10 -10
- package/dist/{data-CgILxDLW.js.map → data-ihsBd9bs.js.map} +1 -1
- package/dist/data.js +7 -7
- package/dist/{experiment-43OJtH7R.js → experiment-DyO54FQB.js} +25 -61
- package/dist/experiment-DyO54FQB.js.map +1 -0
- package/dist/index.js +18 -18
- package/dist/{install-CsPFJSx3.js → install-CFgfRO64.js} +13 -13
- package/dist/{install-CsPFJSx3.js.map → install-CFgfRO64.js.map} +1 -1
- package/dist/install.js +1 -1
- package/dist/{lab-MHzp-_J8.js → lab-B-pLwc5U.js} +10 -10
- package/dist/{lab-MHzp-_J8.js.map → lab-B-pLwc5U.js.map} +1 -1
- package/dist/lab.js +4 -4
- package/dist/{records-B6gpM_3e.js → records-DnK_1Q_S.js} +2 -2
- package/dist/{records-B6gpM_3e.js.map → records-DnK_1Q_S.js.map} +1 -1
- package/dist/{runtime-8bs8EogX.js → runtime-pKfF_iql.js} +9 -9
- package/dist/{runtime-8bs8EogX.js.map → runtime-pKfF_iql.js.map} +1 -1
- package/dist/runtime.js +7 -7
- package/dist/{shell-CywENwBT.js → shell-BIH8Rc21.js} +4 -4
- package/dist/{shell-CywENwBT.js.map → shell-BIH8Rc21.js.map} +1 -1
- package/dist/shell.js +4 -4
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/index.js +2 -2
- package/dist/stores/settings.d.ts +4 -12
- package/dist/styles.css +165 -43
- package/dist/types/platform.d.ts +1 -1
- package/dist/{useExperimentSamples-DHnxKFAF.js → useExperimentSamples-BGN1dmcR.js} +4 -4
- package/dist/{useExperimentSamples-DHnxKFAF.js.map → useExperimentSamples-BGN1dmcR.js.map} +1 -1
- package/dist/{useListReorder-BitdUhxn.js → useListReorder-DPynGrCj.js} +3 -3
- package/dist/{useListReorder-BitdUhxn.js.map → useListReorder-DPynGrCj.js.map} +1 -1
- package/dist/{useRackEditor-DiwCt77M.js → useRackEditor-B2FrQA0p.js} +8 -8
- package/dist/{useRackEditor-DiwCt77M.js.map → useRackEditor-B2FrQA0p.js.map} +1 -1
- package/dist/{useRealtime-C3iy9QkU.js → useRealtime-yWjTTnc9.js} +2 -2
- package/dist/{useRealtime-C3iy9QkU.js.map → useRealtime-yWjTTnc9.js.map} +1 -1
- package/dist/{useRequest-D506eHi8.js → useRequest-Dqw12k2s.js} +3 -3
- package/dist/{useRequest-D506eHi8.js.map → useRequest-Dqw12k2s.js.map} +1 -1
- package/package.json +1 -1
- package/src/__tests__/components/SettingsModal.test.ts +9 -2
- package/src/__tests__/stores/settings.test.ts +21 -21
- package/src/__tests__/styles/paletteTokens.test.ts +44 -0
- package/src/__tests__/styles/v2AuditRules.test.ts +96 -0
- package/src/components/GeneratedResultRenderer.vue +3 -4
- package/src/components/SettingsModal.vue +7 -12
- package/src/stores/index.ts +0 -2
- package/src/stores/settings.ts +20 -50
- package/src/styles/components/app-layout.css +3 -2
- package/src/styles/components/app-top-bar.css +3 -3
- package/src/styles/components/dataframe.css +1 -1
- package/src/styles/components/modal.css +2 -2
- package/src/styles/components/number-input.css +1 -1
- package/src/styles/components/progress-bar.css +3 -3
- package/src/styles/components/section-card.css +4 -2
- package/src/styles/components/settings-modal.css +7 -2
- package/src/styles/variables.css +131 -15
- package/src/types/platform.ts +1 -1
- package/dist/SettingsModal-DO3IZ7qz.js.map +0 -1
- package/dist/experiment-43OJtH7R.js.map +0 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
import { colorPalettes } from '../../stores/settings'
|
|
6
|
+
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const variablesCss = readFileSync(join(resolve(here, '../..'), 'styles/variables.css'), 'utf-8')
|
|
9
|
+
|
|
10
|
+
const ACCENT_TOKENS = [
|
|
11
|
+
'--color-primary',
|
|
12
|
+
'--color-primary-hover',
|
|
13
|
+
'--color-primary-pressed',
|
|
14
|
+
'--color-primary-soft',
|
|
15
|
+
'--color-primary-border',
|
|
16
|
+
]
|
|
17
|
+
const STATUS_TOKENS = ['--mint-success', '--mint-error', '--mint-warning', '--mint-warning-text']
|
|
18
|
+
|
|
19
|
+
/** Declarations of every rule whose selector list has a selector that ends in `[data-palette="<key>"]`. */
|
|
20
|
+
function paletteDeclarations(key: string, dark: boolean): string {
|
|
21
|
+
const attr = `[data-palette="${key}"]`
|
|
22
|
+
return [...variablesCss.matchAll(/([^{}]+)\{([^}]*)\}/g)]
|
|
23
|
+
.filter(([, selector]) => selector.split(',').some((s) => {
|
|
24
|
+
const one = s.trim()
|
|
25
|
+
return one.endsWith(attr) && one.startsWith('html.dark') === dark
|
|
26
|
+
}))
|
|
27
|
+
.map(([, , body]) => body)
|
|
28
|
+
.join('\n')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe('accent palettes', () => {
|
|
32
|
+
it.each(Object.keys(colorPalettes).flatMap((key) => [[key, 'light'], [key, 'dark']]))(
|
|
33
|
+
'should define every accent token for the %s palette in %s mode',
|
|
34
|
+
(key, theme) => {
|
|
35
|
+
const body = paletteDeclarations(key, theme === 'dark')
|
|
36
|
+
for (const token of ACCENT_TOKENS) expect(body, `${key} ${theme} ${token}`).toMatch(new RegExp(`${token}\\s*:`))
|
|
37
|
+
},
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
it('should give the colour-blind palette Okabe-Ito status colours', () => {
|
|
41
|
+
const body = paletteDeclarations('colorblind', false)
|
|
42
|
+
for (const token of STATUS_TOKENS) expect(body, token).toMatch(new RegExp(`${token}\\s*:`))
|
|
43
|
+
})
|
|
44
|
+
})
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { describe, expect, it } from 'vitest'
|
|
5
|
+
|
|
6
|
+
// v2 design audit (2026-10-28) fixes in the SDK stylesheets.
|
|
7
|
+
|
|
8
|
+
const srcRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
|
|
9
|
+
const stylesDir = join(srcRoot, 'styles')
|
|
10
|
+
|
|
11
|
+
function css(path: string): string {
|
|
12
|
+
return readFileSync(join(stylesDir, path), 'utf-8').replace(/\/\*[\s\S]*?\*\//g, '')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function rule(text: string, selector: string): string {
|
|
16
|
+
const escaped = selector.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
17
|
+
return new RegExp(`(?:^|\\})\\s*${escaped}\\s*\\{([^}]*)\\}`).exec(text)?.[1] ?? ''
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const rem = (value: string): number => Number(value.replace('rem', '')) * 16
|
|
21
|
+
|
|
22
|
+
describe('v2 audit style rules', () => {
|
|
23
|
+
it('should keep the outermost cards at least 16px from the window edge', () => {
|
|
24
|
+
const inset = /--mint-page-inset:\s*([\d.]+rem)/.exec(css('variables.css'))?.[1] ?? '0rem'
|
|
25
|
+
expect(rem(inset)).toBeGreaterThanOrEqual(16)
|
|
26
|
+
expect(rule(css('components/app-layout.css'), '.mint-layout--floating')).toMatch(/padding:\s*var\(--mint-page-inset\)/)
|
|
27
|
+
const topBarCard = rule(css('components/app-top-bar.css'), '.mint-topbar--card')
|
|
28
|
+
expect(topBarCard).toMatch(/width:\s*calc\(100% - 2 \* var\(--mint-page-inset\)\)/)
|
|
29
|
+
expect(topBarCard).toMatch(/margin:\s*var\(--mint-page-inset\) var\(--mint-page-inset\) 0/)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should put the SDK utility classes in the utilities layer so host variants beat them', () => {
|
|
33
|
+
const vars = css('variables.css')
|
|
34
|
+
const order = vars.indexOf('@layer theme, base, components, utilities;')
|
|
35
|
+
const layer = vars.indexOf('@layer utilities {')
|
|
36
|
+
expect(order).toBeGreaterThan(-1)
|
|
37
|
+
expect(order).toBeLessThan(vars.indexOf('@layer base {'))
|
|
38
|
+
const utilities = vars.slice(layer, vars.indexOf('@media (prefers-reduced-motion'))
|
|
39
|
+
expect(layer).toBeGreaterThan(-1)
|
|
40
|
+
for (const selector of ['.flex-col {', '.text-text-muted {', '.truncate {', '.max-w-sm {']) {
|
|
41
|
+
expect(utilities).toContain(selector)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('should drop the last DataFrame row rule over the !important cell border', () => {
|
|
46
|
+
const body = rule(css('components/dataframe.css'), '.mint-dataframe__row:last-child .mint-dataframe__td')
|
|
47
|
+
expect(body).toMatch(/border-bottom:\s*none\s*!important/)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('should round the modal close button with --radius-md', () => {
|
|
51
|
+
expect(rule(css('components/modal.css'), '.mint-modal__close')).toMatch(/border-radius:\s*var\(--radius-md\)/)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it('should draw no capsule on the progress rail or the sheet grab hint', () => {
|
|
55
|
+
expect(css('components/progress-bar.css')).not.toMatch(/9999px/)
|
|
56
|
+
expect(rule(css('components/modal.css'), '.mint-modal__grab-hint')).not.toMatch(/9999px/)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('should keep a 28px header control inside the section card header strip', () => {
|
|
60
|
+
const text = css('components/section-card.css')
|
|
61
|
+
const cases: Array<[string, number]> = [
|
|
62
|
+
['.mint-section-card__header', 28],
|
|
63
|
+
['[data-density="comfortable"] .mint-section-card__header', 32],
|
|
64
|
+
]
|
|
65
|
+
for (const [selector, control] of cases) {
|
|
66
|
+
const body = rule(text, selector)
|
|
67
|
+
const minHeight = rem(/min-height:\s*([\d.]+rem)/.exec(body)?.[1] ?? '0rem')
|
|
68
|
+
const padTop = rem(/padding:\s*([\d.]+rem)/.exec(body)?.[1] ?? '0rem')
|
|
69
|
+
expect(control + 2 * padTop + 1, selector).toBeLessThanOrEqual(minHeight)
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
it('should end the settings pane without a closing row hairline and draw no box around the density preview', () => {
|
|
74
|
+
const text = css('components/settings-modal.css')
|
|
75
|
+
const last = rule(
|
|
76
|
+
text,
|
|
77
|
+
'.mint-settings-modal__group:last-of-type > .mint-settings-modal__group-grid > .mint-settings-modal__row:last-child',
|
|
78
|
+
)
|
|
79
|
+
expect(last).toMatch(/border-bottom:\s*none/)
|
|
80
|
+
expect(rule(text, '.mint-settings-modal__density-preview')).not.toMatch(/(^|;)\s*border(-radius)?:/)
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
it('should set the md number input text no smaller than the sm one', () => {
|
|
84
|
+
const text = css('components/number-input.css')
|
|
85
|
+
const size = (variant: string) =>
|
|
86
|
+
rem(/font-size:\s*([\d.]+rem)/.exec(rule(text, `.mint-number-input__input--${variant}`))?.[1] ?? '0rem')
|
|
87
|
+
expect(size('md')).toBeGreaterThan(size('sm'))
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('should give the generated JSON block a token radius and no frame', () => {
|
|
91
|
+
const sfc = readFileSync(join(srcRoot, 'components/GeneratedResultRenderer.vue'), 'utf-8')
|
|
92
|
+
const body = /\.mint-generated-result__json\s*\{([^}]*overflow:[^}]*)\}/.exec(sfc)?.[1] ?? ''
|
|
93
|
+
expect(body).toMatch(/border-radius:\s*var\(--radius-md\)/)
|
|
94
|
+
expect(body).not.toMatch(/(^|;)\s*border:/)
|
|
95
|
+
})
|
|
96
|
+
})
|
|
@@ -130,10 +130,9 @@ function humanize(value: string): string {
|
|
|
130
130
|
|
|
131
131
|
.mint-generated-result__json {
|
|
132
132
|
overflow: auto;
|
|
133
|
-
padding: 1rem;
|
|
134
|
-
border:
|
|
135
|
-
|
|
136
|
-
background: var(--bg-secondary);
|
|
133
|
+
padding: 0.75rem 1rem;
|
|
134
|
+
border-radius: var(--radius-md);
|
|
135
|
+
background: var(--bg-tertiary);
|
|
137
136
|
font-size: 0.8125rem;
|
|
138
137
|
line-height: 1.55;
|
|
139
138
|
white-space: pre-wrap;
|
|
@@ -358,13 +358,8 @@ const themeOptions: { value: ThemeMode; label: string; halves: ('light' | 'dark'
|
|
|
358
358
|
{ value: 'system', label: 'System', halves: ['light', 'dark'] },
|
|
359
359
|
]
|
|
360
360
|
|
|
361
|
-
/**
|
|
362
|
-
|
|
363
|
-
const [from, to] = colorPalettes[key].hues
|
|
364
|
-
const span = ((to - from + 540) % 360) - 180
|
|
365
|
-
const tone = key === 'pastel' ? '60% 72%' : '65% 48%'
|
|
366
|
-
return Array.from({ length: 5 }, (_, i) => `hsl(${Math.round(from + (span * i) / 4)} ${tone})`)
|
|
367
|
-
}
|
|
361
|
+
/** Accent tokens a palette swatch shows; `data-palette` on the strip resolves them per palette. */
|
|
362
|
+
const paletteSwatchTokens = ['--color-primary', '--color-primary-hover', '--color-primary-soft', '--color-primary-border']
|
|
368
363
|
|
|
369
364
|
const densityPreviewRows = [
|
|
370
365
|
['S-0012', '2.41', '12.5'],
|
|
@@ -562,7 +557,7 @@ function canShowForCurrentUser(item: AccessControlled): boolean {
|
|
|
562
557
|
<div class="mint-settings-modal__setting">
|
|
563
558
|
<div class="mint-settings-modal__setting-text">
|
|
564
559
|
<span class="mint-settings-modal__setting-label">Color palette</span>
|
|
565
|
-
<span class="mint-settings-modal__setting-hint">
|
|
560
|
+
<span class="mint-settings-modal__setting-hint">Accent colour across the interface</span>
|
|
566
561
|
</div>
|
|
567
562
|
<div class="mint-settings-modal__palettes">
|
|
568
563
|
<button
|
|
@@ -573,12 +568,12 @@ function canShowForCurrentUser(item: AccessControlled): boolean {
|
|
|
573
568
|
:class="['mint-settings-modal__palette', { 'mint-settings-modal__palette--active': settings.colorPalette === key }]"
|
|
574
569
|
@click="settings.colorPalette = key as ColorPalette"
|
|
575
570
|
>
|
|
576
|
-
<span class="mint-settings-modal__swatches" aria-hidden="true">
|
|
571
|
+
<span class="mint-settings-modal__swatches" :data-palette="key" aria-hidden="true">
|
|
577
572
|
<span
|
|
578
|
-
v-for="
|
|
579
|
-
:key="
|
|
573
|
+
v-for="token in paletteSwatchTokens"
|
|
574
|
+
:key="token"
|
|
580
575
|
class="mint-settings-modal__swatch"
|
|
581
|
-
:style="{ backgroundColor:
|
|
576
|
+
:style="{ backgroundColor: `var(${token})` }"
|
|
582
577
|
/>
|
|
583
578
|
</span>
|
|
584
579
|
<span class="mint-settings-modal__palette-name">{{ palette.name }}</span>
|
package/src/stores/index.ts
CHANGED
package/src/stores/settings.ts
CHANGED
|
@@ -55,39 +55,24 @@ const defaultSettings: SettingsState = {
|
|
|
55
55
|
tableDensity: 'normal',
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
export const colorPalettes: Record<ColorPalette, { name: string; hues: [number, number] }> = {
|
|
59
|
-
default: { name: 'Default (Cyan-Pink)', hues: [180, 320] },
|
|
60
|
-
colorblind: { name: 'Colorblind-friendly', hues: [45, 260] },
|
|
61
|
-
viridis: { name: 'Viridis', hues: [280, 80] },
|
|
62
|
-
pastel: { name: 'Pastel', hues: [200, 340] },
|
|
63
|
-
}
|
|
64
|
-
|
|
65
58
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* The saturation/lightness pairs are lifted from the original indigo/orange
|
|
69
|
-
* tokens in `styles/variables.css` so only the hue moves; the `default`
|
|
70
|
-
* palette writes nothing at all and the stylesheet values stand.
|
|
59
|
+
* Accent palettes. `styles/variables.css` holds each palette's light and dark
|
|
60
|
+
* tokens under `[data-palette]`; the store only writes the attribute.
|
|
71
61
|
*/
|
|
72
|
-
export const
|
|
73
|
-
'
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return
|
|
85
|
-
|
|
86
|
-
'--color-primary-hover': `hsl(${primaryHue} 75% 59%)`,
|
|
87
|
-
'--color-primary-soft': `hsl(${primaryHue} 84% 67% / 0.12)`,
|
|
88
|
-
'--color-cta': `hsl(${accentHue} 95% 53%)`,
|
|
89
|
-
'--color-cta-hover': `hsl(${accentHue} 90% 48%)`,
|
|
90
|
-
}
|
|
62
|
+
export const colorPalettes: Record<ColorPalette, { name: string }> = {
|
|
63
|
+
default: { name: 'Teal' },
|
|
64
|
+
colorblind: { name: 'Colour-blind safe' },
|
|
65
|
+
purple: { name: 'Purple' },
|
|
66
|
+
ocean: { name: 'Ocean' },
|
|
67
|
+
forest: { name: 'Forest' },
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Pre-v2 palette ids and the palette that replaces each one. */
|
|
71
|
+
const RETIRED_PALETTES: Record<string, ColorPalette> = { viridis: 'purple', pastel: 'default' }
|
|
72
|
+
|
|
73
|
+
function knownPalette(value: unknown): ColorPalette {
|
|
74
|
+
if (typeof value === 'string' && value in colorPalettes) return value as ColorPalette
|
|
75
|
+
return (typeof value === 'string' && RETIRED_PALETTES[value]) || 'default'
|
|
91
76
|
}
|
|
92
77
|
|
|
93
78
|
/** `DataFrame`-style size that each table density maps onto. */
|
|
@@ -107,13 +92,13 @@ function loadSettings(): SettingsState {
|
|
|
107
92
|
const stored = localStorage.getItem(STORAGE_KEY)
|
|
108
93
|
if (stored) {
|
|
109
94
|
const parsed = JSON.parse(stored)
|
|
110
|
-
return { ...defaultSettings, ...parsed }
|
|
95
|
+
return { ...defaultSettings, ...parsed, colorPalette: knownPalette(parsed.colorPalette) }
|
|
111
96
|
}
|
|
112
97
|
|
|
113
98
|
const legacyStored = localStorage.getItem(LEGACY_STORAGE_KEY)
|
|
114
99
|
if (legacyStored) {
|
|
115
100
|
const parsed = JSON.parse(legacyStored)
|
|
116
|
-
const migrated = { ...defaultSettings, ...parsed }
|
|
101
|
+
const migrated = { ...defaultSettings, ...parsed, colorPalette: knownPalette(parsed.colorPalette) }
|
|
117
102
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(migrated))
|
|
118
103
|
localStorage.removeItem(LEGACY_STORAGE_KEY)
|
|
119
104
|
return migrated
|
|
@@ -202,20 +187,10 @@ export const useSettingsStore = defineStore('mint-settings', () => {
|
|
|
202
187
|
document.documentElement.classList.toggle('dark', dark)
|
|
203
188
|
}
|
|
204
189
|
|
|
205
|
-
/**
|
|
206
|
-
* Write the selected palette's hues onto `<html>` as custom-property
|
|
207
|
-
* overrides. The `default` palette clears them so `styles/variables.css`
|
|
208
|
-
* keeps ownership of the brand colors.
|
|
209
|
-
*/
|
|
190
|
+
/** Mirror the palette onto `<html data-palette>`; `styles/variables.css` maps it to tokens. */
|
|
210
191
|
function applyPalette() {
|
|
211
192
|
if (typeof document === 'undefined') return
|
|
212
|
-
|
|
213
|
-
const overrides = paletteCssVariables(colorPalette.value)
|
|
214
|
-
for (const name of PALETTE_CSS_VARIABLES) {
|
|
215
|
-
const value = overrides[name]
|
|
216
|
-
if (value) style.setProperty(name, value)
|
|
217
|
-
else style.removeProperty(name)
|
|
218
|
-
}
|
|
193
|
+
document.documentElement.dataset.palette = colorPalette.value
|
|
219
194
|
}
|
|
220
195
|
|
|
221
196
|
/** Mirror the table density onto `<html data-density>` for CSS consumers. */
|
|
@@ -269,10 +244,6 @@ export const useSettingsStore = defineStore('mint-settings', () => {
|
|
|
269
244
|
tableDensity.value = defaultSettings.tableDensity
|
|
270
245
|
}
|
|
271
246
|
|
|
272
|
-
function getPaletteHues(): [number, number] {
|
|
273
|
-
return colorPalettes[colorPalette.value].hues
|
|
274
|
-
}
|
|
275
|
-
|
|
276
247
|
/** The `size` the SDK table components default to for the current density. */
|
|
277
248
|
function getTableSize(): 'sm' | 'md' | 'lg' {
|
|
278
249
|
return tableDensityToSize(tableDensity.value)
|
|
@@ -298,7 +269,6 @@ export const useSettingsStore = defineStore('mint-settings', () => {
|
|
|
298
269
|
applyDensity,
|
|
299
270
|
persistSettings,
|
|
300
271
|
resetToDefaults,
|
|
301
|
-
getPaletteHues,
|
|
302
272
|
getTableSize,
|
|
303
273
|
isDark,
|
|
304
274
|
getApiBaseUrl,
|
|
@@ -60,10 +60,11 @@
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/* Floating variant: all sections appear as separate cards on a background,
|
|
63
|
-
spaced by the density gutter (8px, 12px
|
|
63
|
+
16px from the window edge and spaced by the density gutter (8px, 12px
|
|
64
|
+
comfortable). */
|
|
64
65
|
.mint-layout--floating {
|
|
65
66
|
background-color: var(--bg-primary);
|
|
66
|
-
padding: var(--mint-
|
|
67
|
+
padding: var(--mint-page-inset);
|
|
67
68
|
gap: var(--mint-gutter);
|
|
68
69
|
}
|
|
69
70
|
|
|
@@ -110,10 +110,10 @@
|
|
|
110
110
|
padding: 0 0.375rem 0 0;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
/* Variant: card - flat floating card, inset
|
|
113
|
+
/* Variant: card - flat floating card, inset 16px from the window edge */
|
|
114
114
|
.mint-topbar--card {
|
|
115
|
-
width: calc(100% - 2 * var(--mint-
|
|
116
|
-
margin: var(--mint-
|
|
115
|
+
width: calc(100% - 2 * var(--mint-page-inset));
|
|
116
|
+
margin: var(--mint-page-inset) var(--mint-page-inset) 0;
|
|
117
117
|
padding: 0.375rem 0.5rem 0.375rem 0.625rem;
|
|
118
118
|
border-radius: var(--radius-lg);
|
|
119
119
|
border: 1px solid var(--border-color);
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
width: 2.5rem;
|
|
116
116
|
height: 3px;
|
|
117
117
|
background-color: var(--border-color);
|
|
118
|
-
border-radius:
|
|
118
|
+
border-radius: var(--radius-sm);
|
|
119
119
|
margin: 0.5rem auto 0;
|
|
120
120
|
flex-shrink: 0;
|
|
121
121
|
}
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
width: 1.75rem;
|
|
164
164
|
height: 1.75rem;
|
|
165
165
|
padding: 0;
|
|
166
|
-
border-radius:
|
|
166
|
+
border-radius: var(--radius-md);
|
|
167
167
|
color: var(--text-secondary);
|
|
168
168
|
background: none;
|
|
169
169
|
border: none;
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
/* Horizontal padding matches BaseInput canonical scale (10/12/16) so FormField's
|
|
122
122
|
12px label indent aligns with the numeric text across all input types. */
|
|
123
123
|
.mint-number-input__input--sm { padding: 0.25rem 0.625rem; font-size: 0.8125rem; }
|
|
124
|
-
.mint-number-input__input--md { padding: 0.375rem 0.75rem; font-size: 0.
|
|
124
|
+
.mint-number-input__input--md { padding: 0.375rem 0.75rem; font-size: 0.875rem; }
|
|
125
125
|
.mint-number-input__input--lg { padding: 0.5rem 1rem; font-size: 1rem; }
|
|
126
126
|
|
|
127
127
|
/* ---------- Unit suffix ---------- */
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/* ========================================================================
|
|
25
|
-
Rail variant (default) — single filled track,
|
|
25
|
+
Rail variant (default) — single filled track, square-ish ends (v2: no capsules)
|
|
26
26
|
======================================================================== */
|
|
27
27
|
|
|
28
28
|
.mint-progress__track {
|
|
29
29
|
width: 100%;
|
|
30
30
|
background-color: var(--bg-tertiary);
|
|
31
|
-
border-radius:
|
|
31
|
+
border-radius: var(--radius-sm);
|
|
32
32
|
overflow: hidden;
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
.mint-progress__bar {
|
|
40
40
|
height: 100%;
|
|
41
|
-
border-radius:
|
|
41
|
+
border-radius: var(--radius-sm);
|
|
42
42
|
transition: width 0.3s ease;
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
gap: 0.625rem;
|
|
35
35
|
box-sizing: border-box;
|
|
36
36
|
min-height: 2.5rem;
|
|
37
|
-
padding:
|
|
37
|
+
/* 4px block padding: a 28px header control plus padding plus the 1px rule
|
|
38
|
+
stays inside the 40px strip (6px made it 41px). */
|
|
39
|
+
padding: 0.25rem 0.625rem 0.25rem 0.75rem;
|
|
38
40
|
border-bottom: 1px solid var(--border-color);
|
|
39
41
|
flex-shrink: 0;
|
|
40
42
|
}
|
|
@@ -131,7 +133,7 @@ button.mint-section-card__row:hover {
|
|
|
131
133
|
/* Comfortable density gives the header and rows back their height. */
|
|
132
134
|
[data-density="comfortable"] .mint-section-card__header {
|
|
133
135
|
min-height: 2.75rem;
|
|
134
|
-
padding: 0.
|
|
136
|
+
padding: 0.25rem 0.75rem 0.25rem 0.875rem;
|
|
135
137
|
}
|
|
136
138
|
|
|
137
139
|
[data-density="comfortable"] .mint-section-card__row {
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
border-bottom-color: var(--border-color);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/* The pane ends after the last group's last row: no closing hairline there,
|
|
41
|
+
it would sit on the footer rule with nothing between them. */
|
|
42
|
+
.mint-settings-modal__group:last-of-type > .mint-settings-modal__group-grid > .mint-settings-modal__row:last-child {
|
|
43
|
+
border-bottom: none;
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
/* The field cell anchors the ↺ reset, which sits just left of the control (5d).
|
|
41
47
|
--_settings-control-w is the control's width; stacked fields (text, custom slots)
|
|
42
48
|
keep 0 and put the reset at the right end of their label line. */
|
|
@@ -655,10 +661,9 @@
|
|
|
655
661
|
.mint-settings-modal__density-preview {
|
|
656
662
|
--_density-row: 2.125rem;
|
|
657
663
|
|
|
664
|
+
/* A hairline table in the setting row, not a bordered box inside the modal. */
|
|
658
665
|
grid-column: 1 / -1;
|
|
659
666
|
overflow: hidden;
|
|
660
|
-
border: 1px solid var(--border-color);
|
|
661
|
-
border-radius: var(--radius-md);
|
|
662
667
|
font-size: 0.75rem;
|
|
663
668
|
}
|
|
664
669
|
|