@morscherlab/mint-sdk 1.4.4 → 1.4.6
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/components/SectionCard.vue.d.ts +13 -1
- package/dist/index.js +2 -2
- package/dist/{install-r_GzERvy.js → install-Cbtn69ts.js} +2 -2
- package/dist/{install-r_GzERvy.js.map → install-Cbtn69ts.js.map} +1 -1
- package/dist/install.js +1 -1
- package/dist/{lab-CbdDLAVr.js → lab-C3BmZ2lI.js} +72 -21
- package/dist/lab-C3BmZ2lI.js.map +1 -0
- package/dist/lab.js +1 -1
- package/dist/styles.css +80 -18
- package/dist/styles.d.ts +1 -0
- package/package.json +6 -3
- package/src/__tests__/components/SectionCard.test.ts +33 -0
- package/src/components/InstrumentStatusPanels.vue +3 -3
- package/src/components/SectionCard.vue +42 -6
- package/src/styles/components/section-card.css +65 -6
- package/src/styles/variables.css +4 -2
- package/dist/lab-CbdDLAVr.js.map +0 -1
package/dist/lab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { P as time_exports } from "./records-CWRztE5M.js";
|
|
2
2
|
import { C as FormulaInput_default, L as definePlateEditor, S as useSequenceUtils, a as StepWizard_default, b as MoleculeInput_default, v as ConcentrationInput_default, w as formula_exports, x as SequenceInput_default, y as useConcentrationUnits, z as defineWellPlate } from "./useListReorder-QqJc1dpX.js";
|
|
3
|
-
import { C as defineWellPlateControlProps, S as defineDoseDesignControlModel, T as defineWellPlateDoseControlProps, _ as SampleSelector_default, a as useReagentSeries, c as InstrumentStatusPanels_default, d as ChemicalFormula_default, f as AdductText_default, g as SampleHierarchyTree_default, h as useProtocolTemplates, i as generateDilutionSeries, l as InstrumentStateBadge_default, m as ProtocolStepEditor_default, n as DEFAULT_PRESETS, o as ResourceCard_default, p as ScientificNumber_default, r as DEFAULT_UNITS, s as TimeRangeInput_default, u as SequenceProgressBar_default, v as useSampleGroups, w as defineWellPlateDoseComponentBindings, x as defineDoseCalculatorControlProps } from "./lab-
|
|
3
|
+
import { C as defineWellPlateControlProps, S as defineDoseDesignControlModel, T as defineWellPlateDoseControlProps, _ as SampleSelector_default, a as useReagentSeries, c as InstrumentStatusPanels_default, d as ChemicalFormula_default, f as AdductText_default, g as SampleHierarchyTree_default, h as useProtocolTemplates, i as generateDilutionSeries, l as InstrumentStateBadge_default, m as ProtocolStepEditor_default, n as DEFAULT_PRESETS, o as ResourceCard_default, p as ScientificNumber_default, r as DEFAULT_UNITS, s as TimeRangeInput_default, u as SequenceProgressBar_default, v as useSampleGroups, w as defineWellPlateDoseComponentBindings, x as defineDoseCalculatorControlProps } from "./lab-C3BmZ2lI.js";
|
|
4
4
|
import { C as hexToHsl, E as sampleTypeMarker, S as deriveShade, T as WellPlate_default, _ as mintPlotlyTemplate, b as PlateEditor_default, g as ChartContainer_default, h as PlotlyChart_default, n as ScheduleCalendar_default, r as useScheduleDrag, t as useRackEditor, v as DoseCalculator_default, w as hslToHex, y as dose_exports } from "./useRackEditor-BHGM1Ngz.js";
|
|
5
5
|
export { AdductText_default as AdductText, ChartContainer_default as ChartContainer, ChemicalFormula_default as ChemicalFormula, ConcentrationInput_default as ConcentrationInput, DEFAULT_PRESETS, DEFAULT_UNITS, DoseCalculator_default as DoseCalculator, FormulaInput_default as FormulaInput, InstrumentStateBadge_default as InstrumentStateBadge, InstrumentStatusPanels_default as InstrumentStatusPanels, MoleculeInput_default as MoleculeInput, PlateEditor_default as PlateEditor, PlotlyChart_default as PlotlyChart, ProtocolStepEditor_default as ProtocolStepEditor, ResourceCard_default as ResourceCard, SampleHierarchyTree_default as SampleHierarchyTree, SampleSelector_default as SampleSelector, ScheduleCalendar_default as ScheduleCalendar, ScientificNumber_default as ScientificNumber, SequenceInput_default as SequenceInput, SequenceProgressBar_default as SequenceProgressBar, StepWizard_default as StepWizard, TimeRangeInput_default as TimeRangeInput, WellPlate_default as WellPlate, defineDoseCalculatorControlProps, defineDoseDesignControlModel, definePlateEditor, defineWellPlate, defineWellPlateControlProps, defineWellPlateDoseComponentBindings, defineWellPlateDoseControlProps, deriveShade, dose_exports as dose, formula_exports as formula, generateDilutionSeries, hexToHsl, hslToHex, mintPlotlyTemplate, sampleTypeMarker, time_exports as time, useConcentrationUnits, useProtocolTemplates, useRackEditor, useReagentSeries, useSampleGroups, useScheduleDrag, useSequenceUtils };
|
package/dist/styles.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
.mint-generated-path-input[data-v-85f805b3] {
|
|
3
3
|
display: grid;
|
|
4
4
|
gap: 0.75rem;
|
|
@@ -88,17 +88,17 @@
|
|
|
88
88
|
text-decoration: none;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
.mint-status-panels__tabs[data-v-
|
|
91
|
+
.mint-status-panels__tabs[data-v-1a9246f6] { padding: 0 var(--mint-section-card-inset);
|
|
92
92
|
}
|
|
93
|
-
.mint-status-panels__body[data-v-
|
|
93
|
+
.mint-status-panels__body[data-v-1a9246f6] { padding: 0.75rem var(--mint-section-card-inset);
|
|
94
94
|
}
|
|
95
|
-
.mint-status-panels__bar[data-v-
|
|
95
|
+
.mint-status-panels__bar[data-v-1a9246f6] { display: flex; flex-direction: column; gap: 0.5rem;
|
|
96
96
|
}
|
|
97
|
-
.mint-status-panels__series[data-v-
|
|
97
|
+
.mint-status-panels__series[data-v-1a9246f6] { align-self: flex-end;
|
|
98
98
|
}
|
|
99
|
-
.mint-status-panels__kv[data-v-
|
|
99
|
+
.mint-status-panels__kv[data-v-1a9246f6] { margin: 0; padding: 0.25rem var(--mint-section-card-inset) 0.5rem;
|
|
100
100
|
}
|
|
101
|
-
.mint-status-panels__kv-row[data-v-
|
|
101
|
+
.mint-status-panels__kv-row[data-v-1a9246f6] {
|
|
102
102
|
display: flex;
|
|
103
103
|
align-items: baseline;
|
|
104
104
|
justify-content: space-between;
|
|
@@ -106,11 +106,11 @@
|
|
|
106
106
|
padding: 0.4375rem 0;
|
|
107
107
|
border-bottom: 1px solid var(--border-light);
|
|
108
108
|
}
|
|
109
|
-
.mint-status-panels__kv-row[data-v-
|
|
109
|
+
.mint-status-panels__kv-row[data-v-1a9246f6]:last-child { border-bottom: 0;
|
|
110
110
|
}
|
|
111
|
-
.mint-status-panels__kv-key[data-v-
|
|
111
|
+
.mint-status-panels__kv-key[data-v-1a9246f6] { font-size: 0.75rem; color: var(--text-secondary);
|
|
112
112
|
}
|
|
113
|
-
.mint-status-panels__kv-value[data-v-
|
|
113
|
+
.mint-status-panels__kv-value[data-v-1a9246f6] {
|
|
114
114
|
margin: 0;
|
|
115
115
|
min-width: 0;
|
|
116
116
|
font-family: var(--font-mono);
|
|
@@ -300,9 +300,8 @@
|
|
|
300
300
|
cursor: pointer;
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
|
|
304
|
-
|
|
305
303
|
@layer theme, base, components, utilities;
|
|
304
|
+
|
|
306
305
|
/* MINT SDK Styles - Main entry point
|
|
307
306
|
* This file combines all SDK styles for proper bundling
|
|
308
307
|
*/
|
|
@@ -444,6 +443,9 @@
|
|
|
444
443
|
--mint-gutter: 0.5rem;
|
|
445
444
|
/* Distance from the outermost cards to the window edge, in every density. */
|
|
446
445
|
--mint-page-inset: 1rem;
|
|
446
|
+
/* Text inset of a SectionCard: its title, row text and table edge columns
|
|
447
|
+
start here, and page chrome over a card (breadcrumbs) can line up with it. */
|
|
448
|
+
--mint-section-card-inset: 0.75rem;
|
|
447
449
|
|
|
448
450
|
/* Semantic colors */
|
|
449
451
|
--mint-success: #10B981;
|
|
@@ -687,6 +689,7 @@ html.dark [data-palette="forest"] {
|
|
|
687
689
|
/* Comfortable density (html[data-density], written by the settings store):
|
|
688
690
|
the pre-v2 control heights and a wider gutter. */
|
|
689
691
|
[data-density="comfortable"] {
|
|
692
|
+
--mint-section-card-inset: 0.875rem;
|
|
690
693
|
--form-height-sm: 2rem;
|
|
691
694
|
--form-height-md: 2.25rem;
|
|
692
695
|
--form-height-lg: 3rem;
|
|
@@ -6901,6 +6904,11 @@ html.dark {
|
|
|
6901
6904
|
min-height: 0;
|
|
6902
6905
|
}
|
|
6903
6906
|
|
|
6907
|
+
/* A collapsed fill card gives its track back to its siblings. */
|
|
6908
|
+
.mint-section-card--fill.mint-section-card--collapsed {
|
|
6909
|
+
flex: none;
|
|
6910
|
+
}
|
|
6911
|
+
|
|
6904
6912
|
.mint-section-card--fill .mint-section-card__body {
|
|
6905
6913
|
flex: 1;
|
|
6906
6914
|
min-height: 0;
|
|
@@ -6915,7 +6923,7 @@ html.dark {
|
|
|
6915
6923
|
min-height: 2.5rem;
|
|
6916
6924
|
/* 4px block padding: a 28px header control plus padding plus the 1px rule
|
|
6917
6925
|
stays inside the 40px strip (6px made it 41px). */
|
|
6918
|
-
padding: 0.25rem 0.625rem 0.25rem
|
|
6926
|
+
padding: 0.25rem 0.625rem 0.25rem var(--mint-section-card-inset);
|
|
6919
6927
|
border-bottom: 1px solid var(--border-color);
|
|
6920
6928
|
flex-shrink: 0;
|
|
6921
6929
|
}
|
|
@@ -6924,6 +6932,45 @@ html.dark {
|
|
|
6924
6932
|
border-bottom-color: var(--border-light);
|
|
6925
6933
|
}
|
|
6926
6934
|
|
|
6935
|
+
/* A collapsed card is its header alone: no rule under it. */
|
|
6936
|
+
.mint-section-card__header--collapsed {
|
|
6937
|
+
border-bottom-color: transparent;
|
|
6938
|
+
}
|
|
6939
|
+
|
|
6940
|
+
.mint-section-card__toggle {
|
|
6941
|
+
display: inline-flex;
|
|
6942
|
+
align-items: center;
|
|
6943
|
+
gap: var(--mint-section-card-gap);
|
|
6944
|
+
margin: 0;
|
|
6945
|
+
padding: 0;
|
|
6946
|
+
border: 0;
|
|
6947
|
+
background: none;
|
|
6948
|
+
color: inherit;
|
|
6949
|
+
font: inherit;
|
|
6950
|
+
cursor: pointer;
|
|
6951
|
+
}
|
|
6952
|
+
|
|
6953
|
+
.mint-section-card__toggle:focus-visible {
|
|
6954
|
+
outline: none;
|
|
6955
|
+
box-shadow: var(--focus-ring-offset);
|
|
6956
|
+
border-radius: var(--radius-sm);
|
|
6957
|
+
}
|
|
6958
|
+
|
|
6959
|
+
.mint-section-card__chevron {
|
|
6960
|
+
width: 0.875rem;
|
|
6961
|
+
height: 0.875rem;
|
|
6962
|
+
color: var(--text-muted);
|
|
6963
|
+
transition: transform var(--mint-transition);
|
|
6964
|
+
}
|
|
6965
|
+
|
|
6966
|
+
.mint-section-card__toggle[aria-expanded="false"] .mint-section-card__chevron {
|
|
6967
|
+
transform: rotate(-90deg);
|
|
6968
|
+
}
|
|
6969
|
+
|
|
6970
|
+
.mint-section-card__toggle:hover .mint-section-card__chevron {
|
|
6971
|
+
color: var(--text-secondary);
|
|
6972
|
+
}
|
|
6973
|
+
|
|
6927
6974
|
/* Muted icon, no tinted chip: every accent renders the same. */
|
|
6928
6975
|
.mint-section-card__icon-chip {
|
|
6929
6976
|
display: inline-flex;
|
|
@@ -6971,7 +7018,8 @@ html.dark {
|
|
|
6971
7018
|
display: flex;
|
|
6972
7019
|
align-items: center;
|
|
6973
7020
|
justify-content: space-between;
|
|
6974
|
-
|
|
7021
|
+
/* Text starts on the card inset; controls end where the header's do. */
|
|
7022
|
+
padding: 0.5rem 0.625rem 0.5rem var(--mint-section-card-inset);
|
|
6975
7023
|
border-top: 1px solid var(--border-color);
|
|
6976
7024
|
background: var(--bg-primary);
|
|
6977
7025
|
font-size: 0.75rem;
|
|
@@ -6992,7 +7040,7 @@ html.dark {
|
|
|
6992
7040
|
display: flex;
|
|
6993
7041
|
align-items: center;
|
|
6994
7042
|
gap: var(--mint-section-card-gap);
|
|
6995
|
-
padding: 0.375rem
|
|
7043
|
+
padding: 0.375rem var(--mint-section-card-inset);
|
|
6996
7044
|
background: var(--bg-secondary);
|
|
6997
7045
|
transition: background-color var(--mint-transition);
|
|
6998
7046
|
}
|
|
@@ -7027,14 +7075,28 @@ button.mint-section-card__row:hover {
|
|
|
7027
7075
|
/* Comfortable density gives the header and rows back their height. */
|
|
7028
7076
|
[data-density="comfortable"] .mint-section-card__header {
|
|
7029
7077
|
min-height: 2.75rem;
|
|
7030
|
-
padding: 0.
|
|
7078
|
+
padding-right: 0.75rem;
|
|
7079
|
+
}
|
|
7080
|
+
|
|
7081
|
+
[data-density="comfortable"] .mint-section-card__footer {
|
|
7082
|
+
padding-right: 0.75rem;
|
|
7031
7083
|
}
|
|
7032
7084
|
|
|
7033
7085
|
[data-density="comfortable"] .mint-section-card__row {
|
|
7034
7086
|
padding-top: 0.5rem;
|
|
7035
7087
|
padding-bottom: 0.5rem;
|
|
7036
|
-
|
|
7037
|
-
|
|
7088
|
+
}
|
|
7089
|
+
|
|
7090
|
+
/* A table that is the card body's own child starts and ends on the card's text
|
|
7091
|
+
inset, so its first column lines up under the header title. A table inside a
|
|
7092
|
+
padded wrapper keeps its padding, and the checkbox and actions columns stay
|
|
7093
|
+
centred controls. The table's size padding uses !important, so this must too. */
|
|
7094
|
+
.mint-section-card__body > .mint-dataframe :is(.mint-dataframe__th, .mint-dataframe__td):first-child:not(.mint-dataframe__th--checkbox, .mint-dataframe__td--checkbox) {
|
|
7095
|
+
padding-left: var(--mint-section-card-inset) !important;
|
|
7096
|
+
}
|
|
7097
|
+
|
|
7098
|
+
.mint-section-card__body > .mint-dataframe :is(.mint-dataframe__th, .mint-dataframe__td):last-child:not(.mint-dataframe__th--actions, .mint-dataframe__td--actions) {
|
|
7099
|
+
padding-right: var(--mint-section-card-inset) !important;
|
|
7038
7100
|
}
|
|
7039
7101
|
|
|
7040
7102
|
/* SecretInput — plugin secret settings field with a set / not set / environment status.
|
package/dist/styles.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morscherlab/mint-sdk",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"description": "MINT Platform SDK — Vue 3 components, composables, and types for plugin development. MINT = Mass-spec Infrastructure for Next-generation Toolkits.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -51,7 +51,10 @@
|
|
|
51
51
|
"types": "./dist/types/index.d.ts",
|
|
52
52
|
"import": "./dist/types/index.js"
|
|
53
53
|
},
|
|
54
|
-
"./styles":
|
|
54
|
+
"./styles": {
|
|
55
|
+
"types": "./dist/styles.d.ts",
|
|
56
|
+
"default": "./dist/styles.css"
|
|
57
|
+
}
|
|
55
58
|
},
|
|
56
59
|
"files": [
|
|
57
60
|
"dist",
|
|
@@ -95,7 +98,7 @@
|
|
|
95
98
|
"@vue/test-utils": "2.5.1",
|
|
96
99
|
"happy-dom": "20.14.5",
|
|
97
100
|
"histoire": "1.0.0-beta.1",
|
|
98
|
-
"typescript": "
|
|
101
|
+
"typescript": "6.0.3",
|
|
99
102
|
"vite": "8.3.1",
|
|
100
103
|
"vite-plugin-dts": "5.1.1",
|
|
101
104
|
"vitest": "5.0.2",
|
|
@@ -178,4 +178,37 @@ describe('SectionCard', () => {
|
|
|
178
178
|
expect(withoutFooter.find('.mint-section-card__footer').exists()).toBe(false)
|
|
179
179
|
})
|
|
180
180
|
})
|
|
181
|
+
|
|
182
|
+
describe('collapsible', () => {
|
|
183
|
+
it('should hide the body and emit the collapsed state when a collapsible header is clicked', async () => {
|
|
184
|
+
const wrapper = mount(SectionCard, {
|
|
185
|
+
props: { title: 'Alerts', count: 3, collapsible: true },
|
|
186
|
+
slots: { default: '<p class="body-probe">rows</p>', actions: '<button class="action-probe">Export</button>' },
|
|
187
|
+
attachTo: document.body,
|
|
188
|
+
})
|
|
189
|
+
const toggle = wrapper.find('button.mint-section-card__toggle')
|
|
190
|
+
expect(toggle.attributes('aria-expanded')).toBe('true')
|
|
191
|
+
expect(wrapper.find('h2.mint-section-card__title > button').element).toBe(toggle.element)
|
|
192
|
+
expect(toggle.text()).toContain('Alerts')
|
|
193
|
+
expect(toggle.find('.action-probe').exists()).toBe(false)
|
|
194
|
+
|
|
195
|
+
await toggle.trigger('click')
|
|
196
|
+
|
|
197
|
+
expect(toggle.attributes('aria-expanded')).toBe('false')
|
|
198
|
+
expect(wrapper.find('.mint-section-card__body').isVisible()).toBe(false)
|
|
199
|
+
expect(wrapper.emitted('update:collapsed')).toEqual([[true]])
|
|
200
|
+
wrapper.unmount()
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
it('should keep the body visible with no toggle when collapsed is set without collapsible', () => {
|
|
204
|
+
const wrapper = mount(SectionCard, {
|
|
205
|
+
props: { title: 'Alerts', collapsed: true },
|
|
206
|
+
slots: { default: '<p class="body-probe">rows</p>' },
|
|
207
|
+
attachTo: document.body,
|
|
208
|
+
})
|
|
209
|
+
expect(wrapper.find('.mint-section-card__toggle').exists()).toBe(false)
|
|
210
|
+
expect(wrapper.find('.mint-section-card__body').isVisible()).toBe(true)
|
|
211
|
+
wrapper.unmount()
|
|
212
|
+
})
|
|
213
|
+
})
|
|
181
214
|
})
|
|
@@ -105,11 +105,11 @@ function formatValue(value: string | number | boolean | null): string {
|
|
|
105
105
|
</template>
|
|
106
106
|
|
|
107
107
|
<style scoped>
|
|
108
|
-
.mint-status-panels__tabs { padding: 0
|
|
109
|
-
.mint-status-panels__body { padding: 0.75rem
|
|
108
|
+
.mint-status-panels__tabs { padding: 0 var(--mint-section-card-inset); }
|
|
109
|
+
.mint-status-panels__body { padding: 0.75rem var(--mint-section-card-inset); }
|
|
110
110
|
.mint-status-panels__bar { display: flex; flex-direction: column; gap: 0.5rem; }
|
|
111
111
|
.mint-status-panels__series { align-self: flex-end; }
|
|
112
|
-
.mint-status-panels__kv { margin: 0; padding: 0.25rem
|
|
112
|
+
.mint-status-panels__kv { margin: 0; padding: 0.25rem var(--mint-section-card-inset) 0.5rem; }
|
|
113
113
|
.mint-status-panels__kv-row {
|
|
114
114
|
display: flex;
|
|
115
115
|
align-items: baseline;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/** One-card page region from the MINT 1.1 card system: 12px radius, the
|
|
3
3
|
* single --card-shadow token, a header strip (icon chip, title, mono count,
|
|
4
4
|
* actions), and hairline-separated content — no card-in-card. */
|
|
5
|
-
import { computed } from 'vue'
|
|
5
|
+
import { computed, useId } from 'vue'
|
|
6
6
|
import type { SectionCardAccent, SectionCardDivider } from '../types'
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
@@ -23,6 +23,8 @@ interface Props {
|
|
|
23
23
|
* definite height (a flex or grid track).
|
|
24
24
|
*/
|
|
25
25
|
fill?: boolean
|
|
26
|
+
/** The title toggles the body; bind `v-model:collapsed` to control or keep the state. */
|
|
27
|
+
collapsible?: boolean
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -32,8 +34,14 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
32
34
|
uppercase: false,
|
|
33
35
|
divider: 'strong',
|
|
34
36
|
fill: false,
|
|
37
|
+
collapsible: false,
|
|
35
38
|
})
|
|
36
39
|
|
|
40
|
+
const collapsed = defineModel<boolean>('collapsed', { default: false })
|
|
41
|
+
const bodyId = useId()
|
|
42
|
+
/** `collapsed` hides content only on a card that also shows the toggle to open it again. */
|
|
43
|
+
const hidden = computed(() => props.collapsible && collapsed.value)
|
|
44
|
+
|
|
37
45
|
const iconPaths = computed(() =>
|
|
38
46
|
props.icon === undefined ? [] : Array.isArray(props.icon) ? props.icon : [props.icon],
|
|
39
47
|
)
|
|
@@ -41,6 +49,7 @@ const iconPaths = computed(() =>
|
|
|
41
49
|
const headerClasses = computed(() => [
|
|
42
50
|
'mint-section-card__header',
|
|
43
51
|
props.divider === 'light' ? 'mint-section-card__header--divider-light' : '',
|
|
52
|
+
hidden.value ? 'mint-section-card__header--collapsed' : '',
|
|
44
53
|
])
|
|
45
54
|
|
|
46
55
|
const titleClasses = computed(() => [
|
|
@@ -51,6 +60,7 @@ const titleClasses = computed(() => [
|
|
|
51
60
|
const cardClasses = computed(() => [
|
|
52
61
|
'mint-section-card',
|
|
53
62
|
props.fill ? 'mint-section-card--fill' : '',
|
|
63
|
+
hidden.value ? 'mint-section-card--collapsed' : '',
|
|
54
64
|
])
|
|
55
65
|
</script>
|
|
56
66
|
|
|
@@ -74,20 +84,46 @@ const cardClasses = computed(() => [
|
|
|
74
84
|
<path v-for="(d, i) in iconPaths" :key="i" :d="d" />
|
|
75
85
|
</svg>
|
|
76
86
|
</span>
|
|
77
|
-
|
|
78
|
-
<
|
|
87
|
+
<!-- Disclosure pattern: the button sits inside the heading, never the reverse. -->
|
|
88
|
+
<h2 :class="titleClasses">
|
|
89
|
+
<button
|
|
90
|
+
v-if="collapsible"
|
|
91
|
+
type="button"
|
|
92
|
+
class="mint-section-card__toggle"
|
|
93
|
+
:aria-expanded="!collapsed"
|
|
94
|
+
:aria-controls="bodyId"
|
|
95
|
+
@click="collapsed = !collapsed"
|
|
96
|
+
>
|
|
97
|
+
{{ title }}
|
|
98
|
+
<span v-if="count !== undefined" class="mint-section-card__count">{{ count }}</span>
|
|
99
|
+
<svg
|
|
100
|
+
class="mint-section-card__chevron"
|
|
101
|
+
viewBox="0 0 24 24"
|
|
102
|
+
fill="none"
|
|
103
|
+
stroke="currentColor"
|
|
104
|
+
stroke-width="2"
|
|
105
|
+
stroke-linecap="round"
|
|
106
|
+
stroke-linejoin="round"
|
|
107
|
+
aria-hidden="true"
|
|
108
|
+
>
|
|
109
|
+
<path d="m6 9 6 6 6-6" />
|
|
110
|
+
</svg>
|
|
111
|
+
</button>
|
|
112
|
+
<template v-else>{{ title }}</template>
|
|
113
|
+
</h2>
|
|
114
|
+
<span v-if="count !== undefined && !collapsible" class="mint-section-card__count">{{ count }}</span>
|
|
79
115
|
<div class="mint-section-card__spacer"></div>
|
|
80
116
|
<slot name="actions" />
|
|
81
117
|
</div>
|
|
82
118
|
<!-- Controls belong to the card's chrome, so they sit outside the body and
|
|
83
119
|
stay put while the body scrolls. -->
|
|
84
|
-
<div v-if="$slots.toolbar" class="mint-section-card__toolbar">
|
|
120
|
+
<div v-if="$slots.toolbar" v-show="!hidden" class="mint-section-card__toolbar">
|
|
85
121
|
<slot name="toolbar" />
|
|
86
122
|
</div>
|
|
87
|
-
<div class="mint-section-card__body">
|
|
123
|
+
<div :id="bodyId" v-show="!hidden" class="mint-section-card__body">
|
|
88
124
|
<slot />
|
|
89
125
|
</div>
|
|
90
|
-
<div v-if="$slots.footer" class="mint-section-card__footer">
|
|
126
|
+
<div v-if="$slots.footer" v-show="!hidden" class="mint-section-card__footer">
|
|
91
127
|
<slot name="footer" />
|
|
92
128
|
</div>
|
|
93
129
|
</section>
|
|
@@ -27,6 +27,11 @@
|
|
|
27
27
|
min-height: 0;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/* A collapsed fill card gives its track back to its siblings. */
|
|
31
|
+
.mint-section-card--fill.mint-section-card--collapsed {
|
|
32
|
+
flex: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
30
35
|
.mint-section-card--fill .mint-section-card__body {
|
|
31
36
|
flex: 1;
|
|
32
37
|
min-height: 0;
|
|
@@ -41,7 +46,7 @@
|
|
|
41
46
|
min-height: 2.5rem;
|
|
42
47
|
/* 4px block padding: a 28px header control plus padding plus the 1px rule
|
|
43
48
|
stays inside the 40px strip (6px made it 41px). */
|
|
44
|
-
padding: 0.25rem 0.625rem 0.25rem
|
|
49
|
+
padding: 0.25rem 0.625rem 0.25rem var(--mint-section-card-inset);
|
|
45
50
|
border-bottom: 1px solid var(--border-color);
|
|
46
51
|
flex-shrink: 0;
|
|
47
52
|
}
|
|
@@ -50,6 +55,45 @@
|
|
|
50
55
|
border-bottom-color: var(--border-light);
|
|
51
56
|
}
|
|
52
57
|
|
|
58
|
+
/* A collapsed card is its header alone: no rule under it. */
|
|
59
|
+
.mint-section-card__header--collapsed {
|
|
60
|
+
border-bottom-color: transparent;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.mint-section-card__toggle {
|
|
64
|
+
display: inline-flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
gap: var(--mint-section-card-gap);
|
|
67
|
+
margin: 0;
|
|
68
|
+
padding: 0;
|
|
69
|
+
border: 0;
|
|
70
|
+
background: none;
|
|
71
|
+
color: inherit;
|
|
72
|
+
font: inherit;
|
|
73
|
+
cursor: pointer;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.mint-section-card__toggle:focus-visible {
|
|
77
|
+
outline: none;
|
|
78
|
+
box-shadow: var(--focus-ring-offset);
|
|
79
|
+
border-radius: var(--radius-sm);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.mint-section-card__chevron {
|
|
83
|
+
width: 0.875rem;
|
|
84
|
+
height: 0.875rem;
|
|
85
|
+
color: var(--text-muted);
|
|
86
|
+
transition: transform var(--mint-transition);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.mint-section-card__toggle[aria-expanded="false"] .mint-section-card__chevron {
|
|
90
|
+
transform: rotate(-90deg);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.mint-section-card__toggle:hover .mint-section-card__chevron {
|
|
94
|
+
color: var(--text-secondary);
|
|
95
|
+
}
|
|
96
|
+
|
|
53
97
|
/* Muted icon, no tinted chip: every accent renders the same. */
|
|
54
98
|
.mint-section-card__icon-chip {
|
|
55
99
|
display: inline-flex;
|
|
@@ -97,7 +141,8 @@
|
|
|
97
141
|
display: flex;
|
|
98
142
|
align-items: center;
|
|
99
143
|
justify-content: space-between;
|
|
100
|
-
|
|
144
|
+
/* Text starts on the card inset; controls end where the header's do. */
|
|
145
|
+
padding: 0.5rem 0.625rem 0.5rem var(--mint-section-card-inset);
|
|
101
146
|
border-top: 1px solid var(--border-color);
|
|
102
147
|
background: var(--bg-primary);
|
|
103
148
|
font-size: 0.75rem;
|
|
@@ -118,7 +163,7 @@
|
|
|
118
163
|
display: flex;
|
|
119
164
|
align-items: center;
|
|
120
165
|
gap: var(--mint-section-card-gap);
|
|
121
|
-
padding: 0.375rem
|
|
166
|
+
padding: 0.375rem var(--mint-section-card-inset);
|
|
122
167
|
background: var(--bg-secondary);
|
|
123
168
|
transition: background-color var(--mint-transition);
|
|
124
169
|
}
|
|
@@ -153,12 +198,26 @@ button.mint-section-card__row:hover {
|
|
|
153
198
|
/* Comfortable density gives the header and rows back their height. */
|
|
154
199
|
[data-density="comfortable"] .mint-section-card__header {
|
|
155
200
|
min-height: 2.75rem;
|
|
156
|
-
padding: 0.
|
|
201
|
+
padding-right: 0.75rem;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
[data-density="comfortable"] .mint-section-card__footer {
|
|
205
|
+
padding-right: 0.75rem;
|
|
157
206
|
}
|
|
158
207
|
|
|
159
208
|
[data-density="comfortable"] .mint-section-card__row {
|
|
160
209
|
padding-top: 0.5rem;
|
|
161
210
|
padding-bottom: 0.5rem;
|
|
162
|
-
|
|
163
|
-
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* A table that is the card body's own child starts and ends on the card's text
|
|
214
|
+
inset, so its first column lines up under the header title. A table inside a
|
|
215
|
+
padded wrapper keeps its padding, and the checkbox and actions columns stay
|
|
216
|
+
centred controls. The table's size padding uses !important, so this must too. */
|
|
217
|
+
.mint-section-card__body > .mint-dataframe :is(.mint-dataframe__th, .mint-dataframe__td):first-child:not(.mint-dataframe__th--checkbox, .mint-dataframe__td--checkbox) {
|
|
218
|
+
padding-left: var(--mint-section-card-inset) !important;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.mint-section-card__body > .mint-dataframe :is(.mint-dataframe__th, .mint-dataframe__td):last-child:not(.mint-dataframe__th--actions, .mint-dataframe__td--actions) {
|
|
222
|
+
padding-right: var(--mint-section-card-inset) !important;
|
|
164
223
|
}
|
package/src/styles/variables.css
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
* @import '@morscherlab/mint-sdk/styles';
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap');
|
|
7
|
-
|
|
8
6
|
/* Tailwind v4's layer order, declared first so the SDK's base and utilities
|
|
9
7
|
layers sort the same way with or without Tailwind in the host. */
|
|
10
8
|
@layer theme, base, components, utilities;
|
|
@@ -136,6 +134,9 @@
|
|
|
136
134
|
--mint-gutter: 0.5rem;
|
|
137
135
|
/* Distance from the outermost cards to the window edge, in every density. */
|
|
138
136
|
--mint-page-inset: 1rem;
|
|
137
|
+
/* Text inset of a SectionCard: its title, row text and table edge columns
|
|
138
|
+
start here, and page chrome over a card (breadcrumbs) can line up with it. */
|
|
139
|
+
--mint-section-card-inset: 0.75rem;
|
|
139
140
|
|
|
140
141
|
/* Semantic colors */
|
|
141
142
|
--mint-success: #10B981;
|
|
@@ -379,6 +380,7 @@ html.dark [data-palette="forest"] {
|
|
|
379
380
|
/* Comfortable density (html[data-density], written by the settings store):
|
|
380
381
|
the pre-v2 control heights and a wider gutter. */
|
|
381
382
|
[data-density="comfortable"] {
|
|
383
|
+
--mint-section-card-inset: 0.875rem;
|
|
382
384
|
--form-height-sm: 2rem;
|
|
383
385
|
--form-height-md: 2.25rem;
|
|
384
386
|
--form-height-lg: 3rem;
|