@carbon/layout 12.0.0-alpha.1 → 12.0.0-alpha.2

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/src/index.ts DELETED
@@ -1,221 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2018, 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- // Re-export individual token constants generated from src/dtcg/layout.json
9
- // via the Style Dictionary pipeline (tasks/build.mjs → style-dictionary/sd.config.js).
10
- // The generated file is kept in sync with the DTCG source of truth.
11
- export * from '../js/generated/layout-tokens';
12
-
13
- import { unstable_tokens } from './tokens';
14
- import {
15
- spacing01,
16
- spacing02,
17
- spacing03,
18
- spacing04,
19
- spacing05,
20
- spacing06,
21
- spacing07,
22
- spacing08,
23
- spacing09,
24
- spacing10,
25
- spacing11,
26
- spacing12,
27
- spacing13,
28
- fluidSpacing01,
29
- fluidSpacing02,
30
- fluidSpacing03,
31
- fluidSpacing04,
32
- container01,
33
- container02,
34
- container03,
35
- container04,
36
- container05,
37
- sizeXs,
38
- sizeSm,
39
- sizeMd,
40
- sizeLg,
41
- sizeXl,
42
- size2xl,
43
- iconSize01,
44
- iconSize02,
45
- layout01,
46
- layout02,
47
- layout03,
48
- layout04,
49
- layout05,
50
- layout06,
51
- layout07,
52
- borderRadius00,
53
- borderRadius02,
54
- borderRadius04,
55
- borderRadius08,
56
- borderRadius16,
57
- borderRadius24,
58
- borderRadiusMax,
59
- } from '../js/generated/layout-tokens';
60
-
61
- export { unstable_tokens };
62
-
63
- export type BreakpointName = 'sm' | 'md' | 'lg' | 'xlg' | 'max';
64
- export type Breakpoint = {
65
- width: string;
66
- columns: number;
67
- margin: string;
68
- };
69
- export type SizeName =
70
- | 'XSmall'
71
- | 'Small'
72
- | 'Medium'
73
- | 'Large'
74
- | 'XLarge'
75
- | '2XLarge';
76
- export type BorderRadiusToken =
77
- | 'border-radius-00'
78
- | 'border-radius-02'
79
- | 'border-radius-04'
80
- | 'border-radius-08'
81
- | 'border-radius-16'
82
- | 'border-radius-24'
83
- | 'border-radius-max';
84
-
85
- // Convert
86
- // Default, Use with em() and rem() functions
87
- export const baseFontSize = 16;
88
-
89
- export const rem = (px: number) => {
90
- return `${px / baseFontSize}rem`;
91
- };
92
-
93
- export const em = (px: number) => {
94
- return `${px / baseFontSize}em`;
95
- };
96
-
97
- export const px = (value: number) => {
98
- return `${value}px`;
99
- };
100
-
101
- // Breakpoint
102
- // Initial map of our breakpoints and their values
103
- export const breakpoints: Record<BreakpointName, Breakpoint> = {
104
- sm: {
105
- width: rem(320),
106
- columns: 4,
107
- margin: '0',
108
- },
109
- md: {
110
- width: rem(672),
111
- columns: 8,
112
- margin: rem(16),
113
- },
114
- lg: {
115
- width: rem(1056),
116
- columns: 16,
117
- margin: rem(16),
118
- },
119
- xlg: {
120
- width: rem(1312),
121
- columns: 16,
122
- margin: rem(16),
123
- },
124
- max: {
125
- width: rem(1584),
126
- columns: 16,
127
- margin: rem(24),
128
- },
129
- };
130
-
131
- export const breakpointUp = (name: BreakpointName) => {
132
- return `@media (min-width: ${breakpoints[name].width})`;
133
- };
134
-
135
- export const breakpointDown = (name: BreakpointName) => {
136
- return `@media (max-width: ${breakpoints[name].width})`;
137
- };
138
-
139
- export const breakpoint = breakpointUp;
140
-
141
- // Mini-unit
142
- export const miniUnit = 8;
143
-
144
- export const miniUnits = (count: number) => {
145
- return rem(miniUnit * count);
146
- };
147
-
148
- // Spacing — aggregate array (individual tokens come from generated re-export above)
149
- export const spacing = [
150
- spacing01,
151
- spacing02,
152
- spacing03,
153
- spacing04,
154
- spacing05,
155
- spacing06,
156
- spacing07,
157
- spacing08,
158
- spacing09,
159
- spacing10,
160
- spacing11,
161
- spacing12,
162
- spacing13,
163
- ];
164
-
165
- // Fluid spacing — aggregate array
166
- export const fluidSpacing = [
167
- fluidSpacing01,
168
- fluidSpacing02,
169
- fluidSpacing03,
170
- fluidSpacing04,
171
- ];
172
-
173
- // Layout (deprecated) — aggregate array
174
- export const layout = [
175
- layout01,
176
- layout02,
177
- layout03,
178
- layout04,
179
- layout05,
180
- layout06,
181
- layout07,
182
- ];
183
-
184
- // Container — aggregate array
185
- export const container = [
186
- container01,
187
- container02,
188
- container03,
189
- container04,
190
- container05,
191
- ];
192
-
193
- // Size — camelCase aliases matching the existing SizeName API
194
- export const sizeXSmall = sizeXs;
195
- export const sizeSmall = sizeSm;
196
- export const sizeMedium = sizeMd;
197
- export const sizeLarge = sizeLg;
198
- export const sizeXLarge = sizeXl;
199
- export const size2XLarge = size2xl;
200
- export const sizes: Record<SizeName, string> = {
201
- XSmall: sizeXSmall,
202
- Small: sizeSmall,
203
- Medium: sizeMedium,
204
- Large: sizeLarge,
205
- XLarge: sizeXLarge,
206
- '2XLarge': size2XLarge,
207
- };
208
-
209
- // Icon — aggregate array
210
- export const iconSize = [iconSize01, iconSize02];
211
-
212
- // Border radius — aggregate record keyed by CSS custom property name
213
- export const borderRadius: Record<BorderRadiusToken, string> = {
214
- 'border-radius-00': borderRadius00,
215
- 'border-radius-02': borderRadius02,
216
- 'border-radius-04': borderRadius04,
217
- 'border-radius-08': borderRadius08,
218
- 'border-radius-16': borderRadius16,
219
- 'border-radius-24': borderRadius24,
220
- 'border-radius-max': borderRadiusMax,
221
- };
package/src/tokens.ts DELETED
@@ -1,56 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2018, 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- export const unstable_tokens = [
9
- // Spacing
10
- 'spacing01',
11
- 'spacing02',
12
- 'spacing03',
13
- 'spacing04',
14
- 'spacing05',
15
- 'spacing06',
16
- 'spacing07',
17
- 'spacing08',
18
- 'spacing09',
19
- 'spacing10',
20
- 'spacing11',
21
- 'spacing12',
22
- 'spacing13',
23
-
24
- // Fluid spacing
25
- 'fluidSpacing01',
26
- 'fluidSpacing02',
27
- 'fluidSpacing03',
28
- 'fluidSpacing04',
29
-
30
- // Containers
31
- 'container01',
32
- 'container02',
33
- 'container03',
34
- 'container04',
35
- 'container05',
36
- 'sizeXSmall',
37
- 'sizeSmall',
38
- 'sizeMedium',
39
- 'sizeLarge',
40
- 'sizeXLarge',
41
- 'size2XLarge',
42
-
43
- // Icon sizes
44
- 'iconSize01',
45
- 'iconSize02',
46
-
47
- // Layout
48
- // Deprecated
49
- 'layout01',
50
- 'layout02',
51
- 'layout03',
52
- 'layout04',
53
- 'layout05',
54
- 'layout06',
55
- 'layout07',
56
- ] as const;
@@ -1,104 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2018, 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- /**
11
- * Style Dictionary format — carbon/js-layout
12
- *
13
- * Emits either:
14
- * - An ES module (.js) with `export const camelName = value;`
15
- * - A TypeScript declaration file (.d.ts) with `export declare const camelName: string;`
16
- *
17
- * Token names arrive as kebab-case from SD (e.g. "spacing-01") and are
18
- * converted to camelCase ("spacing01") so the output matches the existing
19
- * hand-authored exports in src/index.ts.
20
- */
21
-
22
- const FILE_BANNER = `// Code generated by @carbon/layout. DO NOT EDIT.
23
- //
24
- // Copyright IBM Corp. 2018, 2026
25
- //
26
- // This source code is licensed under the Apache-2.0 license found in the
27
- // LICENSE file in the root directory of this source tree.
28
- `;
29
-
30
- /**
31
- * Convert kebab-case to camelCase.
32
- * "spacing-01" → "spacing01"
33
- * "fluid-spacing-02" → "fluidSpacing02"
34
- * "border-radius-08" → "borderRadius08"
35
- * "size-xs" → "sizeXs" (kept for completeness; index re-exports under SizeName aliases)
36
- * "icon-size-01" → "iconSize01"
37
- * "layout-03" → "layout03"
38
- *
39
- * @param {string} str
40
- * @returns {string}
41
- */
42
- function kebabToCamel(str) {
43
- return str.replace(/-([a-z0-9])/g, (_, ch) => ch.toUpperCase());
44
- }
45
-
46
- const BASE_FONT_SIZE = 16;
47
- const MINI_UNIT = 8;
48
-
49
- /**
50
- * Resolve a token's raw $value using the carbon.layout.converter extension.
51
- * - "miniUnits": steps × 8px ÷ 16 → rem string
52
- * - "rem": px ÷ 16 → rem string
53
- * - (none): value is already a resolved CSS string, returned as-is
54
- *
55
- * @param {string|number} value
56
- * @param {object|undefined} carbonLayout — token.$extensions?.['carbon.layout']
57
- * @returns {string}
58
- */
59
- function resolveValue(value, carbonLayout) {
60
- const converter = carbonLayout?.converter;
61
- if (converter === 'miniUnits') {
62
- return `${(Number(value) * MINI_UNIT) / BASE_FONT_SIZE}rem`;
63
- }
64
- if (converter === 'rem') {
65
- return `${Number(value) / BASE_FONT_SIZE}rem`;
66
- }
67
- // Unitless zero — preserve as number 0, not the string "0", to match the
68
- // original hand-authored export: `export const fluidSpacing01 = 0`
69
- if (value === '0' || value === 0) return 0;
70
- return String(value);
71
- }
72
-
73
- /**
74
- * @param {{ dictionary: import('style-dictionary').Dictionary, options: object }} args
75
- * @returns {string}
76
- */
77
- function carbonJsLayoutFormat({ dictionary, options }) {
78
- const outputMode = options?.output ?? 'js'; // 'js' | 'dts'
79
- const lines = [FILE_BANNER];
80
-
81
- for (const token of dictionary.allTokens) {
82
- const camelName = kebabToCamel(token.name);
83
- const carbonLayout =
84
- token.$extensions?.['carbon.layout'] ??
85
- token.extensions?.['carbon.layout'];
86
- const resolved = resolveValue(token.value ?? token.$value, carbonLayout);
87
-
88
- const tsType = resolved === 0 ? 'number' : 'string';
89
- if (outputMode === 'js') {
90
- // Numeric 0 is emitted bare (no quotes) to preserve the original type.
91
- const src = resolved === 0 ? '0' : `'${resolved}'`;
92
- lines.push(`export const ${camelName} = ${src};`);
93
- } else {
94
- lines.push(`export declare const ${camelName}: ${tsType};`);
95
- }
96
- }
97
-
98
- return lines.join('\n') + '\n';
99
- }
100
-
101
- module.exports = {
102
- name: 'carbon/js-layout',
103
- format: carbonJsLayoutFormat,
104
- };
@@ -1,188 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2018, 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- /**
11
- * Style Dictionary format — carbon/scss-layout
12
- *
13
- * Generates per-category Sass files from layout.json whose content is
14
- * byte-for-byte identical to what build.mjs / @carbon/scss-generator produced,
15
- * so that nothing downstream breaks.
16
- *
17
- * Files emitted:
18
- * _spacing.scss variables + map, !default
19
- * _fluid-spacing.scss variables + map, !default
20
- * _container.scss variables + map, !default
21
- * _icon-size.scss variables + map, !default
22
- * _border-radius.scss variables + map, !default
23
- * _layout.scss variables + map, !default (deprecated tokens)
24
- * _size.scss bare assignments, no !default, no map
25
- */
26
-
27
- // ── Banners ───────────────────────────────────────────────────────────────────
28
- // Most files use 2023; _size.scss uses 2026 — match exactly.
29
- const BANNER_2023 = `// Code generated by @carbon/layout. DO NOT EDIT.
30
- //
31
- // Copyright IBM Corp. 2018, 2023
32
- //
33
- // This source code is licensed under the Apache-2.0 license found in the
34
- // LICENSE file in the root directory of this source tree.
35
- //`;
36
-
37
- const BANNER_2026 = `// Code generated by @carbon/layout. DO NOT EDIT.
38
- //
39
- // Copyright IBM Corp. 2018, 2026
40
- //
41
- // This source code is licensed under the Apache-2.0 license found in the
42
- // LICENSE file in the root directory of this source tree.
43
- //`;
44
-
45
- const VAR_COMMENT = `/// @type Number
46
- /// @access public
47
- /// @group @carbon/layout`;
48
-
49
- const MAP_COMMENT = `/// @type Map
50
- /// @access public
51
- /// @group @carbon/layout`;
52
-
53
- // ── Constants ─────────────────────────────────────────────────────────────────
54
- const BASE_FONT_SIZE = 16;
55
- const MINI_UNIT = 8;
56
-
57
- /**
58
- * Resolve a token's $value using carbon.layout.converter if present.
59
- * @param {string|number} value
60
- * @param {object|undefined} carbonLayout
61
- * @returns {string}
62
- */
63
- function resolveValue(value, carbonLayout) {
64
- const converter = carbonLayout?.converter;
65
- if (converter === 'miniUnits') {
66
- return `${(Number(value) * MINI_UNIT) / BASE_FONT_SIZE}rem`;
67
- }
68
- if (converter === 'rem') {
69
- return `${Number(value) / BASE_FONT_SIZE}rem`;
70
- }
71
- return String(value);
72
- }
73
-
74
- /**
75
- * Build a standard file: banner + (comment + $var: value !default;) * n + map.
76
- * @param {Array<{name: string, resolved: string}>} tokens
77
- * @param {string} mapName — Sass map variable name
78
- * @param {string} banner
79
- * @returns {string}
80
- */
81
- function buildStandardFile(tokens, mapName, banner) {
82
- const lines = [banner, ''];
83
-
84
- for (const { name, resolved } of tokens) {
85
- lines.push(VAR_COMMENT);
86
- lines.push(`$${name}: ${resolved} !default;`);
87
- lines.push('');
88
- }
89
-
90
- lines.push(MAP_COMMENT);
91
- lines.push(`$${mapName}: (`);
92
- for (const { name } of tokens) {
93
- lines.push(` ${name}: $${name},`);
94
- }
95
- lines.push(');');
96
-
97
- return lines.join('\n') + '\n';
98
- }
99
-
100
- /**
101
- * Build _size.scss — no !default, no map, no per-variable comments.
102
- * @param {Array<{name: string, resolved: string}>} tokens
103
- * @returns {string}
104
- */
105
- function buildSizeFile(tokens) {
106
- const lines = [BANNER_2026, ''];
107
- lines.push(VAR_COMMENT);
108
- for (const { name, resolved } of tokens) {
109
- lines.push(`$${name}: ${resolved};`);
110
- }
111
- return lines.join('\n') + '\n';
112
- }
113
-
114
- /**
115
- * Extract tokens belonging to a DTCG group from the SD dictionary.
116
- * Routing is done by token.path[0] — the group name in the JSON — which is
117
- * the native DTCG mechanism. No prefix inference needed.
118
- *
119
- * @param {import('style-dictionary').Dictionary} dictionary
120
- * @param {string} groupName — top-level DTCG group key (e.g. "spacing")
121
- * @returns {Array<{name: string, resolved: string}>}
122
- */
123
- function tokensForGroup(dictionary, groupName) {
124
- return dictionary.allTokens
125
- .filter((t) => t.path[0] === groupName)
126
- .map((t) => {
127
- const carbonLayout =
128
- t.$extensions?.['carbon.layout'] ?? t.extensions?.['carbon.layout'];
129
- return {
130
- name: t.name,
131
- resolved: resolveValue(t.value ?? t.$value, carbonLayout),
132
- };
133
- });
134
- }
135
-
136
- // ── Format functions — one per DTCG group ─────────────────────────────────────
137
-
138
- function formatSpacing({ dictionary }) {
139
- const tokens = tokensForGroup(dictionary, 'spacing');
140
- return buildStandardFile(tokens, 'spacing', BANNER_2023);
141
- }
142
-
143
- function formatFluidSpacing({ dictionary }) {
144
- const tokens = tokensForGroup(dictionary, 'fluid-spacing');
145
- // Sass expects unitless 0, not the string "0"
146
- const fixed = tokens.map((t) => ({
147
- ...t,
148
- resolved: t.resolved === '0' ? '0' : t.resolved,
149
- }));
150
- return buildStandardFile(fixed, 'fluid-spacing', BANNER_2023);
151
- }
152
-
153
- function formatContainer({ dictionary }) {
154
- const tokens = tokensForGroup(dictionary, 'container');
155
- return buildStandardFile(tokens, 'container', BANNER_2023);
156
- }
157
-
158
- function formatIconSize({ dictionary }) {
159
- const tokens = tokensForGroup(dictionary, 'icon-size');
160
- return buildStandardFile(tokens, 'icon-size', BANNER_2023);
161
- }
162
-
163
- function formatBorderRadius({ dictionary }) {
164
- const tokens = tokensForGroup(dictionary, 'border-radius');
165
- return buildStandardFile(tokens, 'border-radius', BANNER_2023);
166
- }
167
-
168
- function formatLayout({ dictionary }) {
169
- const tokens = tokensForGroup(dictionary, 'layout');
170
- return buildStandardFile(tokens, 'layout', BANNER_2023);
171
- }
172
-
173
- function formatSize({ dictionary }) {
174
- const tokens = tokensForGroup(dictionary, 'size');
175
- return buildSizeFile(tokens);
176
- }
177
-
178
- // ── Exports ───────────────────────────────────────────────────────────────────
179
-
180
- module.exports = [
181
- { name: 'carbon/scss-spacing', format: formatSpacing },
182
- { name: 'carbon/scss-fluid-spacing', format: formatFluidSpacing },
183
- { name: 'carbon/scss-container', format: formatContainer },
184
- { name: 'carbon/scss-icon-size', format: formatIconSize },
185
- { name: 'carbon/scss-border-radius', format: formatBorderRadius },
186
- { name: 'carbon/scss-layout', format: formatLayout },
187
- { name: 'carbon/scss-size', format: formatSize },
188
- ];
@@ -1,104 +0,0 @@
1
- /**
2
- * Copyright IBM Corp. 2018, 2026
3
- *
4
- * This source code is licensed under the Apache-2.0 license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- 'use strict';
9
-
10
- /**
11
- * Style Dictionary configuration for @carbon/layout.
12
- *
13
- * Reads src/dtcg/layout.json and generates:
14
- * scss/generated/*.scss — Sass variables + maps (one file per token group)
15
- * js/generated/layout-tokens.js — ES module named exports
16
- * js/generated/layout-tokens.d.ts — TypeScript declarations
17
- */
18
-
19
- const path = require('path');
20
- const { default: StyleDictionary } = require('style-dictionary');
21
-
22
- const scssFormats = require('./formats/scss-layout');
23
- const carbonJsLayout = require('./formats/js-layout');
24
-
25
- // ── Paths ─────────────────────────────────────────────────────────────────────
26
- const ROOT = path.resolve(__dirname, '..');
27
- const DTCG_SOURCE = path.join(ROOT, 'src', 'dtcg', 'layout.json');
28
- const SCSS_GENERATED = path.join(ROOT, 'scss', 'generated');
29
- const JS_GENERATED = path.join(ROOT, 'js', 'generated');
30
-
31
- // ── Custom name transform ─────────────────────────────────────────────────────
32
- // Uses only the token's own key (last path segment) as the name, discarding
33
- // the group prefix. With DTCG groups, path is ["spacing", "spacing-01"] so
34
- // joining would produce "spacing-spacing-01" — we want just "spacing-01".
35
- const carbonNameKebab = {
36
- name: 'carbon/name-kebab',
37
- type: 'name',
38
- transform(token) {
39
- return token.path[token.path.length - 1];
40
- },
41
- };
42
-
43
- // ── Transform group ───────────────────────────────────────────────────────────
44
- const CARBON_TRANSFORMS = ['attribute/cti', 'carbon/name-kebab'];
45
-
46
- // ── SD config ─────────────────────────────────────────────────────────────────
47
- const config = {
48
- source: [DTCG_SOURCE],
49
- platforms: {
50
- scss: {
51
- transformGroup: 'carbon',
52
- buildPath: SCSS_GENERATED + '/',
53
- files: [
54
- { destination: '_spacing.scss', format: 'carbon/scss-spacing' },
55
- {
56
- destination: '_fluid-spacing.scss',
57
- format: 'carbon/scss-fluid-spacing',
58
- },
59
- { destination: '_container.scss', format: 'carbon/scss-container' },
60
- { destination: '_icon-size.scss', format: 'carbon/scss-icon-size' },
61
- {
62
- destination: '_border-radius.scss',
63
- format: 'carbon/scss-border-radius',
64
- },
65
- { destination: '_layout.scss', format: 'carbon/scss-layout' },
66
- { destination: '_size.scss', format: 'carbon/scss-size' },
67
- ],
68
- },
69
- js: {
70
- transformGroup: 'carbon',
71
- buildPath: JS_GENERATED + '/',
72
- files: [
73
- {
74
- destination: 'layout-tokens.js',
75
- format: 'carbon/js-layout',
76
- options: { output: 'js' },
77
- },
78
- {
79
- destination: 'layout-tokens.d.ts',
80
- format: 'carbon/js-layout',
81
- options: { output: 'dts' },
82
- },
83
- ],
84
- },
85
- },
86
- };
87
-
88
- // ── Build a registered SD instance ────────────────────────────────────────────
89
- function createInstance() {
90
- const sd = new StyleDictionary({});
91
- sd.registerTransform(carbonNameKebab);
92
- sd.registerTransformGroup({ name: 'carbon', transforms: CARBON_TRANSFORMS });
93
- for (const fmt of scssFormats) sd.registerFormat(fmt);
94
- sd.registerFormat(carbonJsLayout);
95
- return sd;
96
- }
97
-
98
- // ── run ───────────────────────────────────────────────────────────────────────
99
- async function run() {
100
- const sd = await createInstance().extend(config);
101
- await sd.buildAllPlatforms();
102
- }
103
-
104
- module.exports = { run };
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "typescript-config-carbon/tsconfig.base.json",
3
- "compilerOptions": {
4
- "declaration": false,
5
- "emitDeclarationOnly": false
6
- },
7
- "include": ["src/**/*"]
8
- }
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "emitDeclarationOnly": true,
6
- "declarationDir": "./lib",
7
- "rootDir": "./src"
8
- },
9
- "include": ["src/**/*"]
10
- }