@opsnow-mcp/opsnow-mcp-common-ui-server 1.0.32 → 1.0.33
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/build/components/examples/opsnow-common-layout-examples-data.js +8 -7
- package/build/components/examples/opsnow-common-select-examples-data.js +10 -10
- package/build/components/opsnow-common-calendar.js +8 -1
- package/build/components/opsnow-common-forms.js +10 -0
- package/build/components/opsnow-common-layout.js +12 -4
- package/build/components/opsnow-common-select.js +16 -12
- package/build/index.js +30 -13
- package/package.json +1 -1
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
export const GridLayoutExamples = [
|
|
3
3
|
{
|
|
4
4
|
title: '4열 그리드 레이아웃',
|
|
5
|
-
description: 'Wrap="nowrap"와
|
|
5
|
+
description: 'Wrap="nowrap"와 간격 토큰(pagePadding·sectionGap·cardPadding·cardGap)을 적용한 4열 레이아웃 예제입니다. 색상 토큰처럼 theme.commonSpacing 을 참조하며 px 하드코딩하지 않습니다.',
|
|
6
6
|
code: `
|
|
7
|
-
<Grid container wrap="nowrap" spacing={0} sx={{ padding:
|
|
7
|
+
<Grid container wrap="nowrap" spacing={0} sx={theme => ({ padding: theme.commonSpacing.pagePadding, gap: theme.commonSpacing.sectionGap })}>
|
|
8
8
|
<Grid item xs={12} sm={6} md={3} key={0}>
|
|
9
|
-
<Box sx={{
|
|
9
|
+
<Box sx={theme => ({
|
|
10
10
|
border: '1px solid #ddd',
|
|
11
11
|
borderRadius: '12px',
|
|
12
|
-
padding:
|
|
12
|
+
padding: theme.commonSpacing.cardPadding,
|
|
13
|
+
gap: theme.commonSpacing.cardGap,
|
|
13
14
|
display: 'flex',
|
|
14
15
|
flexDirection: 'column',
|
|
15
16
|
boxShadow: '2px 2px 8px 0 #4254663D',
|
|
16
|
-
}}>
|
|
17
|
+
})}>
|
|
17
18
|
</Box>
|
|
18
19
|
</Grid>
|
|
19
20
|
<!-- 총 4개 아이템 반복 -->
|
|
@@ -25,7 +26,7 @@ export const GridLayoutExamples = [
|
|
|
25
26
|
title: '2열 그리드 레이아웃',
|
|
26
27
|
description: '2개의 박스를 한 줄에 배치하는 예제입니다.',
|
|
27
28
|
code: `
|
|
28
|
-
<Grid container wrap="nowrap" spacing={0} sx={{ padding:
|
|
29
|
+
<Grid container wrap="nowrap" spacing={0} sx={theme => ({ padding: theme.commonSpacing.pagePadding, gap: theme.commonSpacing.sectionGap })}>
|
|
29
30
|
<Grid item xs={12} md={6} key={0}>
|
|
30
31
|
<Box sx={{ /* 동일한 스타일 */ }}>
|
|
31
32
|
</Box>
|
|
@@ -41,7 +42,7 @@ export const GridLayoutExamples = [
|
|
|
41
42
|
title: '3열 그리드 레이아웃',
|
|
42
43
|
description: '3개의 박스를 한 줄에 배치하는 예제입니다.',
|
|
43
44
|
code: `
|
|
44
|
-
<Grid container wrap="nowrap" spacing={0} sx={{ padding:
|
|
45
|
+
<Grid container wrap="nowrap" spacing={0} sx={theme => ({ padding: theme.commonSpacing.pagePadding, gap: theme.commonSpacing.sectionGap })}>
|
|
45
46
|
<Grid item xs={12} md={4} key={0}>
|
|
46
47
|
<Box sx={{ /* 동일한 스타일 */ }}>
|
|
47
48
|
</Box>
|
|
@@ -61,19 +61,19 @@ export const SelectExamples = [
|
|
|
61
61
|
description: 'outlined variant, small 사이즈, label과 placeholder를 함께 사용하는 다중 선택 셀렉트 예제입니다.'
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
|
-
title: '필터 여러 개 배치 (간격 규칙: 필터 행
|
|
65
|
-
code: `<Stack sx={{ flexDirection: 'row', gap:
|
|
64
|
+
title: '필터 여러 개 배치 (간격 규칙: 필터 행 filterGap(24px), 라벨-필터 filterLabelGap(8px))',
|
|
65
|
+
code: `<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterGap }}>
|
|
66
66
|
<OpsnowCommonSelect items={vendorItems} size="small" variant="outlined" placeholder="벤더" value={vendor} onChange={e => setVendor(e.target.value)} />
|
|
67
|
-
<Stack sx={{ flexDirection: 'row', gap:
|
|
67
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
68
68
|
<OpsnowCommonTypography variant="e-m8">계정 :</OpsnowCommonTypography>
|
|
69
69
|
<OpsnowCommonSelect items={accountItems} size="small" variant="outlined" placeholder="계정 선택" value={account} onChange={e => setAccount(e.target.value)} />
|
|
70
70
|
</Stack>
|
|
71
|
-
<Stack sx={{ flexDirection: 'row', gap:
|
|
71
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
72
72
|
<OpsnowCommonTypography variant="e-m8">리전 :</OpsnowCommonTypography>
|
|
73
73
|
<OpsnowCommonSelect items={regionItems} size="small" variant="outlined" placeholder="리전 선택" value={region} onChange={e => setRegion(e.target.value)} />
|
|
74
74
|
</Stack>
|
|
75
75
|
</Stack>`,
|
|
76
|
-
description: '한 화면에 필터를 여러 개 배치할 때의 간격 규칙 예제입니다. 필터 행
|
|
76
|
+
description: '한 화면에 필터를 여러 개 배치할 때의 간격 규칙 예제입니다. 색상 토큰(theme.palette.commonPalette)과 동일하게 간격도 theme.commonSpacing 토큰을 참조합니다. 필터 행 컨테이너 gap은 theme.commonSpacing.filterGap(24px), 라벨이 있는 필터는 라벨+필터를 theme.commonSpacing.filterLabelGap(8px) Stack으로 감싸며, 그 묶음과 앞 필터 사이는 동일하게 filterGap입니다. px 하드코딩 대신 토큰으로 지정합니다.'
|
|
77
77
|
}
|
|
78
78
|
];
|
|
79
79
|
// Autocomplete(오토컴플리트) 컴포넌트 예제 데이터
|
|
@@ -165,22 +165,22 @@ export const AutocompleteExamples = [
|
|
|
165
165
|
description: 'dropdownMaxWidth prop으로 확장 최대 너비(px)를 지정하는 예제입니다. 드롭다운이 입력 필드보다 넓게 확장되되 지정한 너비(360px)로 제한되고, 그보다 긴 라벨은 줄바꿈됩니다.'
|
|
166
166
|
},
|
|
167
167
|
{
|
|
168
|
-
title: 'Autocomplete - 필터 여러 개 배치 (간격 규칙: 필터 행
|
|
169
|
-
code: `<Stack sx={{ flexDirection: 'row', gap:
|
|
168
|
+
title: 'Autocomplete - 필터 여러 개 배치 (간격 규칙: 필터 행 filterGap(24px), 라벨-필터 filterLabelGap(8px))',
|
|
169
|
+
code: `<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterGap }}>
|
|
170
170
|
<OpsnowCommonAutocomplete items={vendorItems} multiple value={vendors} onChange={setVendors} useCheckboxOption useSelectAll label="벤더" />
|
|
171
|
-
<Stack sx={{ flexDirection: 'row', gap:
|
|
171
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
172
172
|
<OpsnowCommonTypography variant="e-m8">계정 :</OpsnowCommonTypography>
|
|
173
173
|
<Box sx={{ minWidth: 200 }}>
|
|
174
174
|
<OpsnowCommonAutocomplete items={accountItems} multiple value={accounts} onChange={setAccounts} useCheckboxOption useSelectAll />
|
|
175
175
|
</Box>
|
|
176
176
|
</Stack>
|
|
177
|
-
<Stack sx={{ flexDirection: 'row', gap:
|
|
177
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
178
178
|
<OpsnowCommonTypography variant="e-m8">서비스 :</OpsnowCommonTypography>
|
|
179
179
|
<Box sx={{ minWidth: 200 }}>
|
|
180
180
|
<OpsnowCommonAutocomplete items={serviceItems} value={service} onChange={setService} />
|
|
181
181
|
</Box>
|
|
182
182
|
</Stack>
|
|
183
183
|
</Stack>`,
|
|
184
|
-
description: '한 화면에 필터를 여러 개 배치할 때의 간격 규칙 예제입니다. 필터 행
|
|
184
|
+
description: '한 화면에 필터를 여러 개 배치할 때의 간격 규칙 예제입니다. 색상 토큰(theme.palette.commonPalette)과 동일하게 간격도 theme.commonSpacing 토큰을 참조합니다. 필터 행 컨테이너 gap은 theme.commonSpacing.filterGap(24px), 라벨이 있는 필터는 라벨+필터를 theme.commonSpacing.filterLabelGap(8px) Stack으로 감싸며, 그 묶음과 앞 필터 사이는 동일하게 filterGap입니다. px 하드코딩 대신 토큰으로 지정하고, Autocomplete는 Box(minWidth)로 최소 폭을 확보합니다. Select와 Autocomplete를 섞어 배치할 때도 같은 규칙이 적용됩니다.'
|
|
185
185
|
}
|
|
186
186
|
];
|
|
@@ -65,7 +65,14 @@ export function createCalendarComponent() {
|
|
|
65
65
|
name: "createCalendar",
|
|
66
66
|
description: `캘린더 컴포넌트 - 날짜 선택 및 이벤트 관리
|
|
67
67
|
**주의사항:**
|
|
68
|
-
- 선택된 날짜를 표시할 때 selectedDate가 null인 경우 'None'으로 표시됩니다.
|
|
68
|
+
- 선택된 날짜를 표시할 때 selectedDate가 null인 경우 'None'으로 표시됩니다.
|
|
69
|
+
**필터로 배치할 때 간격 규칙 (다른 필터(Select/Autocomplete)와 함께 한 행에 둘 때, Select와 동일, px 하드코딩 금지):**
|
|
70
|
+
- 필터 행 컨테이너 gap: theme.commonSpacing.filterGap (24px)
|
|
71
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterGap }}>
|
|
72
|
+
- "기간 : <DatePicker>"처럼 라벨이 붙으면 라벨+DatePicker를 theme.commonSpacing.filterLabelGap (8px) Stack으로 감쌈
|
|
73
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
74
|
+
- 색상 토큰(theme.palette.commonPalette)과 동일하게 theme.commonSpacing 참조. 순수 CSS는 var(--opsnow-spacing-filter-gap) / var(--opsnow-spacing-filter-label-gap)
|
|
75
|
+
|
|
69
76
|
**사용 예시:**
|
|
70
77
|
\`\`\`jsx
|
|
71
78
|
<p>
|
|
@@ -1004,6 +1004,11 @@ export function createFormsComponent() {
|
|
|
1004
1004
|
name: "createInsightCard",
|
|
1005
1005
|
description: `InsightCard 컴포넌트 - AI 인사이트, 로딩 상태 등 지원
|
|
1006
1006
|
|
|
1007
|
+
**간격 규칙 (여러 카드/섹션을 배치할 때, px 하드코딩 금지):**
|
|
1008
|
+
- 카드(섹션 그룹) 사이 간격: theme.commonSpacing.sectionGap (24px)
|
|
1009
|
+
- 카드 내부 요소 간 간격: theme.commonSpacing.cardGap (16px)
|
|
1010
|
+
- 색상 토큰(theme.palette.commonPalette)과 동일하게 theme.commonSpacing 참조. 순수 CSS는 var(--opsnow-spacing-section-gap) / var(--opsnow-spacing-card-gap)
|
|
1011
|
+
|
|
1007
1012
|
**import:**
|
|
1008
1013
|
\`\`\`javascript
|
|
1009
1014
|
import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
|
|
@@ -1051,6 +1056,11 @@ export function createFormsComponent() {
|
|
|
1051
1056
|
name: "createInsightContent",
|
|
1052
1057
|
description: `InsightContent 컴포넌트 - 타일 없이 AI 인사이트 콘텐츠만 표시
|
|
1053
1058
|
|
|
1059
|
+
**간격 규칙 (콘텐츠를 카드/섹션 안에 조합할 때, px 하드코딩 금지):**
|
|
1060
|
+
- 카드 내부 요소 간 간격: theme.commonSpacing.cardGap (16px)
|
|
1061
|
+
- 섹션(카드 그룹) 사이 간격: theme.commonSpacing.sectionGap (24px)
|
|
1062
|
+
- 색상 토큰(theme.palette.commonPalette)과 동일하게 theme.commonSpacing 참조
|
|
1063
|
+
|
|
1054
1064
|
**import:**
|
|
1055
1065
|
\`\`\`javascript
|
|
1056
1066
|
import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
|
|
@@ -42,6 +42,13 @@ export function createGridLayoutComponent() {
|
|
|
42
42
|
name: "createGridLayout",
|
|
43
43
|
description: `Grid 및 Box 기반 레이아웃 생성
|
|
44
44
|
|
|
45
|
+
**간격 규칙 (px 하드코딩 금지, 색상 토큰처럼 theme.commonSpacing 참조):**
|
|
46
|
+
- 페이지/그리드 컨테이너 패딩: theme.commonSpacing.pagePadding (24px)
|
|
47
|
+
- 섹션(카드 그룹) 사이 간격: theme.commonSpacing.sectionGap (24px) — Grid container의 gap
|
|
48
|
+
- 카드(Box) 내부 패딩: theme.commonSpacing.cardPadding ('16px 20px')
|
|
49
|
+
- 카드 내부 요소 간 간격: theme.commonSpacing.cardGap (16px)
|
|
50
|
+
- 값이 여러 개이므로 sx는 콜백 형태로: sx={theme => ({ padding: theme.commonSpacing.pagePadding, gap: theme.commonSpacing.sectionGap })}
|
|
51
|
+
|
|
45
52
|
**import:**
|
|
46
53
|
\`\`\`jsx
|
|
47
54
|
import { Box, Grid } from '@mui/material';
|
|
@@ -56,20 +63,21 @@ export function createGridLayoutComponent() {
|
|
|
56
63
|
.map(([k, v]) => `${k}={${v}}`)
|
|
57
64
|
.join(" ");
|
|
58
65
|
return ` <Grid item ${bpProps} key={${i}}>` +
|
|
59
|
-
`\n <Box sx={{` +
|
|
66
|
+
`\n <Box sx={theme => ({` +
|
|
60
67
|
`\n border: '1px solid #ddd',` +
|
|
61
68
|
`\n borderRadius: '12px',` +
|
|
62
|
-
`\n padding:
|
|
69
|
+
`\n padding: theme.commonSpacing.cardPadding,` +
|
|
70
|
+
`\n gap: theme.commonSpacing.cardGap,` +
|
|
63
71
|
`\n display: 'flex',` +
|
|
64
72
|
`\n flexDirection: 'column',` +
|
|
65
73
|
`\n boxShadow: '2px 2px 8px 0 #4254663D',` +
|
|
66
|
-
`\n }}>` +
|
|
74
|
+
`\n })}>` +
|
|
67
75
|
`\n ${item}` +
|
|
68
76
|
`\n </Box>` +
|
|
69
77
|
`\n </Grid>`;
|
|
70
78
|
}).join("\n");
|
|
71
79
|
const code = [
|
|
72
|
-
`<Grid container wrap="nowrap" spacing={0} sx={{ padding:
|
|
80
|
+
`<Grid container wrap="nowrap" spacing={0} sx={theme => ({ padding: theme.commonSpacing.pagePadding, gap: theme.commonSpacing.sectionGap })}>`,
|
|
73
81
|
gridItems,
|
|
74
82
|
`</Grid>`,
|
|
75
83
|
].join("\n");
|
|
@@ -56,12 +56,14 @@ export function createSelectComponent() {
|
|
|
56
56
|
- value/onChange는 단일/다중 선택에 따라 배열 또는 단일 값
|
|
57
57
|
|
|
58
58
|
**필터 배치 간격 규칙 (한 화면에 필터 여러 개 배치 시 무조건 적용):**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- 간격은
|
|
59
|
+
색상 토큰(theme.palette.commonPalette)과 동일하게, 간격도 시맨틱 토큰 theme.commonSpacing 을 참조합니다 (px 하드코딩 금지).
|
|
60
|
+
- 필터를 감싸는 행(row) 컨테이너 gap은 theme.commonSpacing.filterGap (= 24px):
|
|
61
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterGap }}>
|
|
62
|
+
- "계정 : <필터>"처럼 라벨이 붙는 경우 라벨+필터를 theme.commonSpacing.filterLabelGap (= 8px) Stack으로 감쌈:
|
|
63
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
64
|
+
- 라벨이 있는 필터도 앞 필터와의 간격은 동일하게 filterGap (라벨+필터 묶음 전체가 하나의 필터로 취급됨)
|
|
65
|
+
- 간격은 spacing prop이나 px 하드코딩이 아니라 theme.commonSpacing 토큰으로 지정 (theme.commonSpacing. 까지 치면 자동완성)
|
|
66
|
+
- theme 컨텍스트를 못 쓰는 순수 CSS는 var(--opsnow-spacing-filter-gap) / var(--opsnow-spacing-filter-label-gap) 사용
|
|
65
67
|
- 필터가 많아 화면 폭을 넘칠 수 있으면 행 컨테이너에 flexWrap: 'wrap' 추가 (선택)
|
|
66
68
|
|
|
67
69
|
**import:**
|
|
@@ -109,12 +111,14 @@ export function createSelectComponent() {
|
|
|
109
111
|
- value/onChange는 단일/다중 선택에 따라 배열 또는 단일 값
|
|
110
112
|
|
|
111
113
|
**필터 배치 간격 규칙 (한 화면에 필터 여러 개 배치 시 무조건 적용):**
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
- 간격은
|
|
114
|
+
색상 토큰(theme.palette.commonPalette)과 동일하게, 간격도 시맨틱 토큰 theme.commonSpacing 을 참조합니다 (px 하드코딩 금지).
|
|
115
|
+
- 필터를 감싸는 행(row) 컨테이너 gap은 theme.commonSpacing.filterGap (= 24px):
|
|
116
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterGap }}>
|
|
117
|
+
- "계정 : <필터>"처럼 라벨이 붙는 경우 라벨+필터를 theme.commonSpacing.filterLabelGap (= 8px) Stack으로 감쌈:
|
|
118
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
119
|
+
- 라벨이 있는 필터도 앞 필터와의 간격은 동일하게 filterGap (라벨+필터 묶음 전체가 하나의 필터로 취급됨)
|
|
120
|
+
- 간격은 spacing prop이나 px 하드코딩이 아니라 theme.commonSpacing 토큰으로 지정 (theme.commonSpacing. 까지 치면 자동완성)
|
|
121
|
+
- theme 컨텍스트를 못 쓰는 순수 CSS는 var(--opsnow-spacing-filter-gap) / var(--opsnow-spacing-filter-label-gap) 사용
|
|
118
122
|
- 필터가 많아 화면 폭을 넘칠 수 있으면 행 컨테이너에 flexWrap: 'wrap' 추가 (선택)
|
|
119
123
|
|
|
120
124
|
**import:**
|
package/build/index.js
CHANGED
|
@@ -84,28 +84,45 @@ Before implementing OpsnowCommonDataGrid, you MUST use getUIExamples tool with '
|
|
|
84
84
|
|
|
85
85
|
Reference example: "Search + Pagination"
|
|
86
86
|
|
|
87
|
-
**CRITICAL:
|
|
87
|
+
**CRITICAL: Spacing Tokens (theme.commonSpacing) — DO NOT hardcode px**
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
Just like color tokens (theme.palette.commonPalette), all layout spacing uses the semantic token theme.commonSpacing
|
|
90
|
+
(requires @opsnow-common/opsnow-common-style 1.0.11+, type-augmented → autocompletes, light/dark 공통):
|
|
90
91
|
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
filterGap 24px - gap between filters (filter row gap)
|
|
93
|
+
filterLabelGap 8px - gap between label and its filter
|
|
94
|
+
filterRowGap 12px - marginBottom below a filter row
|
|
95
|
+
sectionGap 24px - gap between sections (card groups)
|
|
96
|
+
cardGap 16px - gap between elements inside a card
|
|
97
|
+
cardPadding '16px 20px' - padding of a filter bar / card container
|
|
98
|
+
pagePadding 24px - page content padding
|
|
99
|
+
|
|
100
|
+
Use theme in sx/styled: sx={theme => ({ gap: theme.commonSpacing.filterGap })} or sx={{ gap: theme => theme.commonSpacing.filterLabelGap }}.
|
|
101
|
+
Pure CSS (no theme context): var(--opsnow-spacing-filter-gap), --opsnow-spacing-filter-label-gap, --opsnow-spacing-section-gap, --opsnow-spacing-card-gap, --opsnow-spacing-card-padding, --opsnow-spacing-page-padding, --opsnow-spacing-filter-row-gap.
|
|
102
|
+
Outside theme context (constants/utils): import { commonSpacing } from '@opsnow-common/opsnow-common-style'; commonSpacing.filterGap // '24px'.
|
|
103
|
+
Found hardcoded px spacing? You MUST replace it: (1) use the token for that purpose → (2) if none fits, use theme.spacing(n) for generic multiples (base 4px → theme.spacing(2) = 8px) → (3) still nothing? DO NOT keep px — ask to add a new token in the style package (one row).
|
|
104
|
+
|
|
105
|
+
--- Filter layout (Select/Autocomplete/DatePicker/DataGrid search area) ---
|
|
106
|
+
When placing multiple filters in one row, the gap values are MANDATORY:
|
|
107
|
+
|
|
108
|
+
[CORRECT] Row container MUST use theme.commonSpacing.filterGap (24px), label+filter group MUST use theme.commonSpacing.filterLabelGap (8px):
|
|
109
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterGap }}>
|
|
93
110
|
<OpsnowCommonSelect ... />
|
|
94
|
-
<Stack sx={{ flexDirection: 'row', gap:
|
|
111
|
+
<Stack sx={{ flexDirection: 'row', gap: theme => theme.commonSpacing.filterLabelGap }}>
|
|
95
112
|
<OpsnowCommonTypography variant="e-m8">계정 :</OpsnowCommonTypography>
|
|
96
113
|
<OpsnowCommonAutocomplete ... />
|
|
97
114
|
</Stack>
|
|
98
115
|
</Stack>
|
|
99
116
|
|
|
100
|
-
[FORBIDDEN] DO NOT place filters without gap:
|
|
101
|
-
<Stack direction="row">
|
|
102
|
-
|
|
103
|
-
<OpsnowCommonSelect ... />
|
|
104
|
-
</Stack>
|
|
117
|
+
[FORBIDDEN] DO NOT hardcode px and DO NOT place filters without gap:
|
|
118
|
+
<Stack direction="row" sx={{ gap: '24px' }}> <- px 하드코딩 금지, 토큰 사용!
|
|
119
|
+
<Stack direction="row"> <- gap 누락 금지!
|
|
105
120
|
|
|
106
|
-
- Adjacent filters: 24px
|
|
107
|
-
- Label and its filter: 8px
|
|
108
|
-
- A labeled group counts as ONE filter — still
|
|
121
|
+
- Adjacent filters: theme.commonSpacing.filterGap (24px) — token, NOT hardcoded px or spacing prop
|
|
122
|
+
- Label and its filter: theme.commonSpacing.filterLabelGap (8px) — wrap label+filter in one Stack
|
|
123
|
+
- A labeled group counts as ONE filter — still filterGap from the previous filter
|
|
124
|
+
- Pure CSS (no theme context): use var(--opsnow-spacing-filter-gap) / var(--opsnow-spacing-filter-label-gap)
|
|
125
|
+
- Requires @opsnow-common/opsnow-common-style 1.0.11+ (theme.commonSpacing is type-augmented → autocompletes)
|
|
109
126
|
|
|
110
127
|
WARNING: Violating these rules will cause the UI to malfunction.`
|
|
111
128
|
});
|