sh-ui-cli 0.111.0 → 0.113.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.
@@ -2,6 +2,30 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$description": "sh-ui 릴리즈 노트 단일 소스. docs(React)와 showcase(Flutter)가 함께 읽는다. 새 릴리즈마다 맨 앞에 추가.",
4
4
  "versions": [
5
+ {
6
+ "version": "0.113.0",
7
+ "date": "2026-05-26",
8
+ "title": "components — Separator label 슬롯 + align",
9
+ "type": "minor",
10
+ "highlights": [
11
+ "**`Separator` 라벨 슬롯 신규** — `<Separator />` 는 기존처럼 가로/세로 1px 선이지만, `<Separator>섹션 라벨</Separator>` 처럼 children 을 넘기면 가운데 라벨이 있는 `──── label ────` 형식으로 렌더. 라벨이 있을 땐 horizontal 로 강제되고 `align` prop(`start`/`center`/`end`) 으로 라벨 위치를 정한다. 기존 사용처는 그대로 — children 없는 호출은 동작 변화 없음.",
12
+ "**디자인 토큰 활용** — 선 색은 `--border`, 라벨은 `--foreground-subtle` + uppercase + tracking-wide 가 기본. 시안 빈도 높은 \"섹션 라벨 양옆 1px 선\" 패턴 (login OAuth 구분, 워크스페이스 스위처 invite 섹션 등) 을 1줄로 줄여준다. `className` 으로 라벨 컨테이너의 typography·spacing 도 override 가능.",
13
+ "**Tailwind / CSS Modules / plain CSS 세 변종 모두 갱신** — 라벨이 있을 때만 `flex items-center gap` 컨테이너로 전환되고 plain 변종은 컨테이너 자체에 background 를 두지 않아 visual side effect 없음."
14
+ ],
15
+ "url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.113.0"
16
+ },
17
+ {
18
+ "version": "0.112.0",
19
+ "date": "2026-05-22",
20
+ "title": "template — sh-ui-discipline ESLint 룰을 모노레포 스캐폴드에 기본 박음",
21
+ "type": "minor",
22
+ "highlights": [
23
+ "**`@workspace/eslint-config/sh-ui-discipline` 신규 export** — 모노레포 스캐폴드 시 `packages/eslint-config/sh-ui-discipline.js` 가 함께 생성. `no-restricted-syntax` 로 native `<button>`·`<input>`·`<select>`·`<textarea>`·`<label>` JSX 금지 + `@workspace/ui-core` 의 대응 컴포넌트 안내. AI 가 시안 mimic 으로 native + Tailwind 를 쓰는 패턴을 lint 단계에서 자동 차단 — 디자인 시스템 우회를 시끄럽게 실패시킨다.",
24
+ "**`nextjs-app` (fsd/flat/mes 3 arch) + `vite-app` 의 `eslint.config.js` 가 자동 적용** — 스캐폴드 직후 새 앱이 즉시 룰을 받는다. 예외는 `// eslint-disable-next-line no-restricted-syntax -- <이유>` 인라인 override.",
25
+ "**severity** — 모노레포 기본 `eslint-plugin-only-warn` 이 error → warning 다운그레이드. CI hard-fail 은 lint 스크립트에서 `--max-warnings 0` 으로 강제."
26
+ ],
27
+ "url": "https://github.com/sanghyeonKim0201/sh-ui/releases/tag/v0.112.0"
28
+ },
5
29
  {
6
30
  "version": "0.111.0",
7
31
  "date": "2026-05-22",
@@ -4,42 +4,74 @@ import styles from "./styles.module.css";
4
4
 
5
5
  import { cn } from "@SH_UI_UTILS@";
6
6
  export type SeparatorOrientation = "horizontal" | "vertical";
7
+ export type SeparatorAlign = "start" | "center" | "end";
7
8
 
8
9
  export interface SeparatorProps
9
10
  extends Omit<React.HTMLAttributes<HTMLDivElement>, "role"> {
10
11
  orientation?: SeparatorOrientation;
12
+ /**
13
+ * 라벨 정렬 — children 이 있을 때만 의미를 가진다. 기본 center.
14
+ */
15
+ align?: SeparatorAlign;
11
16
  /**
12
17
  * 의미 없는 시각적 구분선인지 여부. 기본 true(aria-hidden).
13
- * 스크린리더에도 섹션 구분을 알려야 하면 false.
14
18
  */
15
19
  decorative?: boolean;
16
20
  }
17
21
 
18
22
  /**
19
- * 시각적 구분선. 가로(height=1px) / 세로(width=1px).
20
- *
21
- * 의미 있는 구분에는 `decorative={false}`로 role=separator가 붙고, 그렇지 않으면
22
- * aria-hidden 처리되어 보조 기술에 노출되지 않는다.
23
+ * 시각적 구분선 (CSS Modules 변종). 두 변종을 한 컴포넌트로:
24
+ * - children 없음: 가로/세로 1px
25
+ * - children 있음: 가운데 라벨이 있는 "──── label ────" 형식
23
26
  */
24
27
  export const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(
25
28
  function Separator(
26
- { className, orientation = "horizontal", decorative = true, ...props },
29
+ {
30
+ className,
31
+ orientation = "horizontal",
32
+ align = "center",
33
+ decorative = true,
34
+ children,
35
+ ...props
36
+ },
27
37
  ref,
28
38
  ) {
39
+ const hasLabel = children != null && children !== false;
40
+ if (!hasLabel) {
41
+ return (
42
+ <div
43
+ ref={ref}
44
+ role={decorative ? undefined : "separator"}
45
+ aria-orientation={decorative ? undefined : orientation}
46
+ aria-hidden={decorative || undefined}
47
+ data-orientation={orientation}
48
+ className={cn(
49
+ styles.separator,
50
+ styles[`separator--${orientation}`],
51
+ className,
52
+ )}
53
+ {...props}
54
+ />
55
+ );
56
+ }
29
57
  return (
30
58
  <div
31
59
  ref={ref}
32
60
  role={decorative ? undefined : "separator"}
33
- aria-orientation={decorative ? undefined : orientation}
34
- aria-hidden={decorative || undefined}
35
- data-orientation={orientation}
36
- className={cn(
37
- styles.separator,
38
- styles[`separator--${orientation}`],
39
- className,
40
- )}
61
+ aria-orientation={decorative ? undefined : "horizontal"}
62
+ data-orientation="horizontal"
63
+ data-align={align}
64
+ className={cn(styles.separator__labeled, className)}
41
65
  {...props}
42
- />
66
+ >
67
+ {align !== "start" ? (
68
+ <span aria-hidden className={styles.separator__line} />
69
+ ) : null}
70
+ <span className={styles.separator__label}>{children}</span>
71
+ {align !== "end" ? (
72
+ <span aria-hidden className={styles.separator__line} />
73
+ ) : null}
74
+ </div>
43
75
  );
44
76
  },
45
77
  );
@@ -3,37 +3,79 @@ import * as React from "react";
3
3
 
4
4
  import { cn } from "@SH_UI_UTILS@";
5
5
  export type SeparatorOrientation = "horizontal" | "vertical";
6
+ export type SeparatorAlign = "start" | "center" | "end";
6
7
 
7
8
  export interface SeparatorProps
8
9
  extends Omit<React.HTMLAttributes<HTMLDivElement>, "role"> {
9
10
  orientation?: SeparatorOrientation;
11
+ /**
12
+ * 라벨 정렬 — children 이 있을 때만 의미를 가진다. 기본 center.
13
+ */
14
+ align?: SeparatorAlign;
10
15
  /**
11
16
  * 의미 없는 시각적 구분선인지 여부. 기본 true(aria-hidden).
12
- * 스크린리더에도 섹션 구분을 알려야 하면 false.
13
17
  */
14
18
  decorative?: boolean;
15
19
  }
16
20
 
17
21
  /**
18
- * 시각적 구분선 (Tailwind utility 변종). 가로(height=1px) / 세로(width=1px).
22
+ * 시각적 구분선 (Tailwind utility 변종). 변종을 한 컴포넌트로:
23
+ * - children 없음: 가로(height=1px) / 세로(width=1px)
24
+ * - children 있음: 가운데에 라벨이 있는 "──── label ────" 형식
19
25
  */
20
26
  export const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(
21
27
  function Separator(
22
- { className, orientation = "horizontal", decorative = true, ...props },
28
+ {
29
+ className,
30
+ orientation = "horizontal",
31
+ align = "center",
32
+ decorative = true,
33
+ children,
34
+ ...props
35
+ },
23
36
  ref,
24
37
  ) {
25
- const sizing =
26
- orientation === "horizontal" ? "w-full h-px" : "w-px h-full self-stretch";
38
+ const hasLabel = children != null && children !== false;
39
+ if (!hasLabel) {
40
+ const sizing =
41
+ orientation === "horizontal"
42
+ ? "w-full h-px"
43
+ : "w-px h-full self-stretch";
44
+ return (
45
+ <div
46
+ ref={ref}
47
+ role={decorative ? undefined : "separator"}
48
+ aria-orientation={decorative ? undefined : orientation}
49
+ aria-hidden={decorative || undefined}
50
+ data-orientation={orientation}
51
+ className={cn("bg-border shrink-0", sizing, className)}
52
+ {...props}
53
+ />
54
+ );
55
+ }
27
56
  return (
28
57
  <div
29
58
  ref={ref}
30
59
  role={decorative ? undefined : "separator"}
31
- aria-orientation={decorative ? undefined : orientation}
32
- aria-hidden={decorative || undefined}
33
- data-orientation={orientation}
34
- className={cn("bg-border shrink-0", sizing, className)}
60
+ aria-orientation={decorative ? undefined : "horizontal"}
61
+ data-orientation="horizontal"
62
+ data-align={align}
63
+ className={cn(
64
+ "flex w-full shrink-0 items-center gap-[var(--space-3,0.75rem)]",
65
+ className,
66
+ )}
35
67
  {...props}
36
- />
68
+ >
69
+ {align !== "start" ? (
70
+ <span aria-hidden className="h-px flex-1 bg-border" />
71
+ ) : null}
72
+ <span className="text-[length:var(--text-xs,0.75rem)] font-semibold uppercase tracking-[0.04em] text-foreground-subtle">
73
+ {children}
74
+ </span>
75
+ {align !== "end" ? (
76
+ <span aria-hidden className="h-px flex-1 bg-border" />
77
+ ) : null}
78
+ </div>
37
79
  );
38
80
  },
39
81
  );
@@ -4,10 +4,16 @@ import "./styles.css";
4
4
 
5
5
  import { cn } from "@SH_UI_UTILS@";
6
6
  export type SeparatorOrientation = "horizontal" | "vertical";
7
+ export type SeparatorAlign = "start" | "center" | "end";
7
8
 
8
9
  export interface SeparatorProps
9
10
  extends Omit<React.HTMLAttributes<HTMLDivElement>, "role"> {
10
11
  orientation?: SeparatorOrientation;
12
+ /**
13
+ * 라벨 정렬 — children 이 있을 때만 의미를 가진다. 기본 center.
14
+ * `start` 면 라벨이 왼쪽에 붙고 오른쪽으로만 선이 뻗는다 (반대도 마찬가지).
15
+ */
16
+ align?: SeparatorAlign;
11
17
  /**
12
18
  * 의미 없는 시각적 구분선인지 여부. 기본 true(aria-hidden).
13
19
  * 스크린리더에도 섹션 구분을 알려야 하면 false.
@@ -16,30 +22,62 @@ export interface SeparatorProps
16
22
  }
17
23
 
18
24
  /**
19
- * 시각적 구분선. 가로(height=1px) / 세로(width=1px).
25
+ * 시각적 구분선. 변종을 한 컴포넌트로:
26
+ * - children 없음: 가로/세로 1px 선 (orientation 으로 선택)
27
+ * - children 있음: 가운데에 라벨이 있는 "──── label ────" 형식
28
+ * (horizontal 강제, align 으로 라벨 위치 지정)
20
29
  *
21
- * 의미 있는 구분에는 `decorative={false}`로 role=separator가 붙고, 그렇지 않으면
22
- * aria-hidden 처리되어 보조 기술에 노출되지 않는다.
30
+ * 의미 있는 구분에는 `decorative={false}` role=separator 가 붙고,
31
+ * 그렇지 않으면 aria-hidden 처리되어 보조 기술에 노출되지 않는다.
23
32
  */
24
33
  export const Separator = React.forwardRef<HTMLDivElement, SeparatorProps>(
25
34
  function Separator(
26
- { className, orientation = "horizontal", decorative = true, ...props },
35
+ {
36
+ className,
37
+ orientation = "horizontal",
38
+ align = "center",
39
+ decorative = true,
40
+ children,
41
+ ...props
42
+ },
27
43
  ref,
28
44
  ) {
45
+ const hasLabel = children != null && children !== false;
46
+ if (!hasLabel) {
47
+ return (
48
+ <div
49
+ ref={ref}
50
+ role={decorative ? undefined : "separator"}
51
+ aria-orientation={decorative ? undefined : orientation}
52
+ aria-hidden={decorative || undefined}
53
+ data-orientation={orientation}
54
+ className={cn(
55
+ "sh-ui-separator",
56
+ `sh-ui-separator--${orientation}`,
57
+ className,
58
+ )}
59
+ {...props}
60
+ />
61
+ );
62
+ }
29
63
  return (
30
64
  <div
31
65
  ref={ref}
32
66
  role={decorative ? undefined : "separator"}
33
- aria-orientation={decorative ? undefined : orientation}
34
- aria-hidden={decorative || undefined}
35
- data-orientation={orientation}
36
- className={cn(
37
- "sh-ui-separator",
38
- `sh-ui-separator--${orientation}`,
39
- className,
40
- )}
67
+ aria-orientation={decorative ? undefined : "horizontal"}
68
+ data-orientation="horizontal"
69
+ data-align={align}
70
+ className={cn("sh-ui-separator--labeled", className)}
41
71
  {...props}
42
- />
72
+ >
73
+ {align !== "start" ? (
74
+ <span aria-hidden className="sh-ui-separator__line" />
75
+ ) : null}
76
+ <span className="sh-ui-separator__label">{children}</span>
77
+ {align !== "end" ? (
78
+ <span aria-hidden className="sh-ui-separator__line" />
79
+ ) : null}
80
+ </div>
43
81
  );
44
82
  },
45
83
  );
@@ -13,3 +13,24 @@
13
13
  height: 100%;
14
14
  align-self: stretch;
15
15
  }
16
+
17
+ /* labeled — children 있을 때 적용. 컨테이너 자체에는 배경 없음 (내부 .line 만 1px). */
18
+ .sh-ui-separator--labeled {
19
+ display: flex;
20
+ align-items: center;
21
+ gap: var(--space-3, 0.75rem);
22
+ width: 100%;
23
+ flex-shrink: 0;
24
+ }
25
+ .sh-ui-separator__line {
26
+ flex: 1;
27
+ height: 1px;
28
+ background: var(--border);
29
+ }
30
+ .sh-ui-separator__label {
31
+ font-size: var(--text-xs, 0.75rem);
32
+ font-weight: 600;
33
+ text-transform: uppercase;
34
+ letter-spacing: 0.04em;
35
+ color: var(--foreground-subtle);
36
+ }
@@ -13,3 +13,23 @@
13
13
  height: 100%;
14
14
  align-self: stretch;
15
15
  }
16
+
17
+ .separator__labeled {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: var(--space-3, 0.75rem);
21
+ width: 100%;
22
+ flex-shrink: 0;
23
+ }
24
+ .separator__line {
25
+ flex: 1;
26
+ height: 1px;
27
+ background: var(--border);
28
+ }
29
+ .separator__label {
30
+ font-size: var(--text-xs, 0.75rem);
31
+ font-weight: 600;
32
+ text-transform: uppercase;
33
+ letter-spacing: 0.04em;
34
+ color: var(--foreground-subtle);
35
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$description": "컴포넌트별 토큰 의존성 (var(--*) 추출). build-registry-tokens.mjs 가 자동 생성.",
3
- "$generated": "2026-05-21T07:02:56.611Z",
3
+ "$generated": "2026-05-26T05:20:38.023Z",
4
4
  "components": {
5
5
  "button": {
6
6
  "plain": [
@@ -1486,11 +1486,13 @@
1486
1486
  },
1487
1487
  "separator": {
1488
1488
  "plain": [
1489
- "--border"
1489
+ "--border",
1490
+ "--foreground-subtle"
1490
1491
  ],
1491
1492
  "tailwind": [],
1492
1493
  "css-modules": [
1493
- "--border"
1494
+ "--border",
1495
+ "--foreground-subtle"
1494
1496
  ],
1495
1497
  "vanilla-extract": []
1496
1498
  },
@@ -35,7 +35,7 @@
35
35
  "badge": "상태 뱃지 — variant, size.",
36
36
  "progress": "선형 진행률 — value 0~100, indeterminate.",
37
37
  "spinner": "로딩 스피너 — size.",
38
- "separator": "구분선 — orientation(horizontal/vertical).",
38
+ "separator": "구분선 — 두 변종 한 컴포넌트: children 없으면 가로/세로 1px 선(orientation), children 있으면 가운데 라벨 \"── label ──\"(align=start/center/end, horizontal 강제). decorative={false} 시 role=separator.",
39
39
  "skeleton": "스켈레톤 로딩 플레이스홀더.",
40
40
  "code-panel": "Shiki 기반 코드 하이라이트 패널 — 복사 버튼 포함.",
41
41
  "code-tabs": "여러 코드 뷰(예: React/Flutter, 강조/전체)를 탭으로 전환 — Tabs + CodePanel 합성, 각 탭 내용은 CodePanelProps 그대로.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sh-ui-cli",
3
- "version": "0.111.0",
3
+ "version": "0.113.0",
4
4
  "description": "sh-ui CLI — 프로젝트 스캐폴드(create) + 컴포넌트 추가(add/list/remove) + IDE-내 AI용 MCP 서버",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,6 +30,7 @@ export const TEMPLATE_MANIFEST = {
30
30
  "packages/eslint-config/next.js",
31
31
  "packages/eslint-config/package.json",
32
32
  "packages/eslint-config/react-internal.js",
33
+ "packages/eslint-config/sh-ui-discipline.js",
33
34
  "packages/typescript-config/base.json",
34
35
  "packages/typescript-config/nextjs.json",
35
36
  "packages/typescript-config/package.json",
@@ -9,7 +9,8 @@
9
9
  "./react-internal": "./react-internal.js",
10
10
  "./fsd": "./fsd.js",
11
11
  "./flat": "./flat.js",
12
- "./mes": "./mes.js"
12
+ "./mes": "./mes.js",
13
+ "./sh-ui-discipline": "./sh-ui-discipline.js"
13
14
  },
14
15
  "devDependencies": {
15
16
  "@eslint/js": "^9.39.2",
@@ -0,0 +1,62 @@
1
+ /**
2
+ * sh-ui 컴포넌트 우선 — native JSX 요소 금지 ESLint config.
3
+ *
4
+ * 시안 HTML 의 raw `<button class="btn-primary">` 같은 패턴을 Tailwind 로
5
+ * 그대로 옮기지 말고 `@workspace/ui-core` 의 sh-ui 컴포넌트를 사용한다.
6
+ * AI 가 시안 mimic 으로 native 를 쓰는 패턴을 자동 차단 — 디자인 시스템의
7
+ * 우회를 lint 단계에서 시끄럽게 실패시킨다.
8
+ *
9
+ * 사용 (앱의 eslint.config.js 에서):
10
+ * import { shUiDisciplineConfig } from "@workspace/eslint-config/sh-ui-discipline"
11
+ * export default [ ...otherConfigs, ...shUiDisciplineConfig ]
12
+ *
13
+ * 적용 범위: `**\/*.tsx` (앱 코드만 — `packages/ui/ui-core` 의 컴포넌트는
14
+ * 정의상 native 를 감싸므로 자체 lint 또는 별도 설정으로 분리).
15
+ *
16
+ * 진짜 필요한 예외(file/hidden input, form action 등) 만 인라인 override:
17
+ * // eslint-disable-next-line no-restricted-syntax -- <구체적 이유>
18
+ * <button ...>
19
+ *
20
+ * severity: monorepo 기본 `eslint-plugin-only-warn` 이 error → warning
21
+ * 다운그레이드한다. CI 에서 hard fail 하려면 lint 스크립트에 `--max-warnings 0`.
22
+ *
23
+ * Link 가 button 처럼 보여야 하면: sh-ui Button 의 `buttonVariants` cva 를
24
+ * 재사용한 helper 컴포넌트를 만들어 `<Link>` 에 적용한다.
25
+ *
26
+ * @type {import("eslint").Linter.Config[]}
27
+ */
28
+ export const shUiDisciplineConfig = [
29
+ {
30
+ files: ["**/*.tsx"],
31
+ rules: {
32
+ "no-restricted-syntax": [
33
+ "error",
34
+ {
35
+ selector: "JSXOpeningElement[name.name='button']",
36
+ message:
37
+ "native <button> 금지 — '@workspace/ui-core/components/button' 의 <Button> 사용. Link 가 button 처럼 보여야 하면 sh-ui Button 의 buttonVariants 를 재사용한 helper 컴포넌트. 예외 시 // eslint-disable-next-line no-restricted-syntax -- <이유> 주석.",
38
+ },
39
+ {
40
+ selector: "JSXOpeningElement[name.name='input']",
41
+ message:
42
+ "native <input> 금지 — '@workspace/ui-core/components/input' 의 <Input> 사용. type='hidden' 같은 예외는 // eslint-disable-next-line 주석.",
43
+ },
44
+ {
45
+ selector: "JSXOpeningElement[name.name='select']",
46
+ message:
47
+ "native <select> 금지 — '@workspace/ui-core/components/select' 의 <Select> 사용.",
48
+ },
49
+ {
50
+ selector: "JSXOpeningElement[name.name='textarea']",
51
+ message:
52
+ "native <textarea> 금지 — '@workspace/ui-core/components/textarea' 의 <Textarea> 사용.",
53
+ },
54
+ {
55
+ selector: "JSXOpeningElement[name.name='label']",
56
+ message:
57
+ "native <label> 금지 — '@workspace/ui-core/components/label' 의 <Label> 사용.",
58
+ },
59
+ ],
60
+ },
61
+ },
62
+ ]
@@ -1,5 +1,6 @@
1
1
  import { nextJsConfig } from "@workspace/eslint-config/next-js"
2
2
  import { flatConfig } from "@workspace/eslint-config/flat"
3
+ import { shUiDisciplineConfig } from "@workspace/eslint-config/sh-ui-discipline"
3
4
 
4
5
  export default [
5
6
  {
@@ -7,4 +8,5 @@ export default [
7
8
  },
8
9
  ...nextJsConfig,
9
10
  ...flatConfig,
11
+ ...shUiDisciplineConfig,
10
12
  ]
@@ -1,5 +1,6 @@
1
1
  import { nextJsConfig } from "@workspace/eslint-config/next-js"
2
2
  import { mesConfig } from "@workspace/eslint-config/mes"
3
+ import { shUiDisciplineConfig } from "@workspace/eslint-config/sh-ui-discipline"
3
4
 
4
5
  export default [
5
6
  {
@@ -7,4 +8,5 @@ export default [
7
8
  },
8
9
  ...nextJsConfig,
9
10
  ...mesConfig,
11
+ ...shUiDisciplineConfig,
10
12
  ]
@@ -1,5 +1,6 @@
1
1
  import { nextJsConfig } from "@workspace/eslint-config/next-js"
2
2
  import { fsdConfig } from "@workspace/eslint-config/fsd"
3
+ import { shUiDisciplineConfig } from "@workspace/eslint-config/sh-ui-discipline"
3
4
 
4
5
  export default [
5
6
  {
@@ -7,4 +8,5 @@ export default [
7
8
  },
8
9
  ...nextJsConfig,
9
10
  ...fsdConfig,
11
+ ...shUiDisciplineConfig,
10
12
  ]
@@ -1,3 +1,4 @@
1
1
  import { config } from "@workspace/eslint-config/react-internal"
2
+ import { shUiDisciplineConfig } from "@workspace/eslint-config/sh-ui-discipline"
2
3
 
3
- export default config
4
+ export default [...config, ...shUiDisciplineConfig]