@primer/primitives 8.0.0 → 8.1.0-rc.313f1fc7

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.
@@ -1,7 +0,0 @@
1
- @media (pointer: coarse) {
2
- :root {
3
- --control-minTarget-auto: 2.75rem;
4
- --controlStack-small-gap-auto: 1rem;
5
- --controlStack-medium-gap-auto: 0.75rem;
6
- }
7
- }
@@ -1,7 +0,0 @@
1
- @media (pointer: fine) {
2
- :root {
3
- --control-minTarget-auto: 1rem;
4
- --controlStack-small-gap-auto: 0.5rem;
5
- --controlStack-medium-gap-auto: 0.5rem;
6
- }
7
- }
@@ -22,8 +22,8 @@
22
22
  --text-display-size: 2.5rem;
23
23
  --text-display-lineBoxHeight: 1.4;
24
24
  --fontStack-monospace: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas, Liberation Mono, monospace;
25
- --fontStack-sansSerif: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
26
- --fontStack-system: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
25
+ --fontStack-sansSerif: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
26
+ --fontStack-system: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
27
27
  --text-codeInline-weight: var(--base-text-weight-normal);
28
28
  --text-codeBlock-weight: var(--base-text-weight-normal);
29
29
  --text-caption-weight: var(--base-text-weight-normal);
@@ -34,14 +34,14 @@
34
34
  --text-title-weight-large: var(--base-text-weight-semibold);
35
35
  --text-display-weight: var(--base-text-weight-medium);
36
36
  --text-codeInline-shorthand: var(--text-codeInline-weight) var(--text-codeInline-size) var(--fontStack-monospace);
37
- --text-codeBlock-shorthand: var(--text-codeBlock-weight) var(--text-codeBlock-size)/var(--text-codeBlock-lineHeight) var(--fontStack-monospace);
38
- --text-caption-shorthand: var(--text-caption-weight) var(--text-caption-size)/var(--text-caption-lineHeight) var(--fontStack-sansSerif);
39
- --text-body-shorthand-small: var(--text-body-weight) var(--text-body-size-small)/var(--text-body-lineHeight-small) var(--fontStack-sansSerif);
40
- --text-body-shorthand-medium: var(--text-body-weight) var(--text-body-size-medium)/var(--text-body-lineHeight-medium) var(--fontStack-sansSerif);
41
- --text-body-shorthand-large: var(--text-body-weight) var(--text-body-size-large)/var(--text-body-lineHeight-large) var(--fontStack-sansSerif);
42
- --text-subtitle-shorthand: var(--text-subtitle-weight) var(--text-subtitle-size)/var(--text-subtitle-lineHeight) var(--fontStack-sansSerif);
43
- --text-title-shorthand-small: var(--text-title-weight-small) var(--text-title-size-small)/var(--text-title-lineHeight-small) var(--fontStack-sansSerif);
44
- --text-title-shorthand-medium: var(--text-title-weight-medium) var(--text-title-size-medium)/var(--text-title-lineHeight-medium) var(--fontStack-sansSerif);
45
- --text-title-shorthand-large: var(--text-title-weight-large) var(--text-title-size-large)/var(--text-title-lineHeight-large) var(--fontStack-sansSerif);
46
- --text-display-shorthand: var(--text-display-weight) var(--text-display-size)/var(--text-display-lineHeight) var(--fontStack-sansSerif);
37
+ --text-codeBlock-shorthand: var(--text-codeBlock-weight) var(--text-codeBlock-size) / var(--text-codeBlock-lineHeight) var(--fontStack-monospace);
38
+ --text-caption-shorthand: var(--text-caption-weight) var(--text-caption-size) / var(--text-caption-lineHeight) var(--fontStack-sansSerif);
39
+ --text-body-shorthand-small: var(--text-body-weight) var(--text-body-size-small) / var(--text-body-lineHeight-small) var(--fontStack-sansSerif);
40
+ --text-body-shorthand-medium: var(--text-body-weight) var(--text-body-size-medium) / var(--text-body-lineHeight-medium) var(--fontStack-sansSerif);
41
+ --text-body-shorthand-large: var(--text-body-weight) var(--text-body-size-large) / var(--text-body-lineHeight-large) var(--fontStack-sansSerif);
42
+ --text-subtitle-shorthand: var(--text-subtitle-weight) var(--text-subtitle-size) / var(--text-subtitle-lineHeight) var(--fontStack-sansSerif);
43
+ --text-title-shorthand-small: var(--text-title-weight-small) var(--text-title-size-small) / var(--text-title-lineHeight-small) var(--fontStack-sansSerif);
44
+ --text-title-shorthand-medium: var(--text-title-weight-medium) var(--text-title-size-medium) / var(--text-title-lineHeight-medium) var(--fontStack-sansSerif);
45
+ --text-title-shorthand-large: var(--text-title-weight-large) var(--text-title-size-large) / var(--text-title-lineHeight-large) var(--fontStack-sansSerif);
46
+ --text-display-shorthand: var(--text-display-weight) var(--text-display-size) / var(--text-display-lineHeight) var(--fontStack-sansSerif);
47
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primer/primitives",
3
- "version": "8.0.0",
3
+ "version": "8.1.0-rc.313f1fc7",
4
4
  "description": "Typography, spacing, and color primitives for Primer design system",
5
5
  "files": [
6
6
  "dist",
@@ -23,7 +23,8 @@
23
23
  },
24
24
  "homepage": "https://github.com/primer/primitives#readme",
25
25
  "scripts": {
26
- "build:next": "npm run build:v8 && npm run build:fallbacks && npm run build:figma",
26
+ "build": "npm run build:v8 && npm run build:fallbacks && npm run build:figma",
27
+ "build:next": "echo '\\033[31m 🛑 Use npm run build instead of npm run build:next\\033[0m'",
27
28
  "build:v8": "ts-node ./scripts/buildTokens.ts",
28
29
  "build:fallbacks": "ts-node ./scripts/buildFallbacks.ts",
29
30
  "build:figma": "ts-node scripts/buildFigma.ts",
@@ -36,11 +37,9 @@
36
37
  "lint:fix": "eslint '**/*.{js,ts,tsx,md,mdx}' --fix --max-warnings=0 --config .eslintrc.js",
37
38
  "lint:tokens": "ts-node ./scripts/validateTokenJson.ts",
38
39
  "prebuild": "rm -rf dist",
39
- "prebuild:next": "rm -rf dist",
40
- "prepack": "npm run build:next",
41
- "prepare": "husky",
40
+ "prepack": "npm run build",
42
41
  "release": "changeset publish",
43
- "start:storybook": "npm run build:next && cd docs/storybook && npm run storybook",
42
+ "start:storybook": "npm run build && cd docs/storybook && npm run storybook",
44
43
  "test": "jest --verbose --coverage"
45
44
  },
46
45
  "prettier": "@github/prettier-config",
@@ -69,7 +68,6 @@
69
68
  "eslint-plugin-react": "^7.29.4",
70
69
  "eslint-plugin-react-hooks": "^4.4.0",
71
70
  "eslint-plugin-storybook": "^0.6.15",
72
- "husky": "^9.0.11",
73
71
  "jest": "^29.6.1",
74
72
  "json5": "^2.2.1",
75
73
  "markdown-table-ts": "^1.0.3",
@@ -30,12 +30,10 @@ import {
30
30
  javascriptEsm,
31
31
  typescriptExportDefinition,
32
32
  jsonNestedPrefixed,
33
- cssThemed,
34
33
  cssCustomMedia,
35
34
  jsonOneDimensional,
36
35
  jsonPostCssFallback,
37
- cssWrapMediaQuery,
38
- cssVariables,
36
+ cssAdvanced,
39
37
  jsonFigma,
40
38
  } from './formats'
41
39
 
@@ -50,8 +48,8 @@ StyleDictionary.registerParser(w3cJsonParser)
50
48
  *
51
49
  */
52
50
  StyleDictionary.registerFormat({
53
- name: 'css/themed',
54
- formatter: cssThemed,
51
+ name: 'css/advanced',
52
+ formatter: cssAdvanced,
55
53
  })
56
54
 
57
55
  StyleDictionary.registerFormat({
@@ -59,16 +57,6 @@ StyleDictionary.registerFormat({
59
57
  formatter: cssCustomMedia,
60
58
  })
61
59
 
62
- StyleDictionary.registerFormat({
63
- name: 'css/wrapMediaQuery',
64
- formatter: cssWrapMediaQuery,
65
- })
66
-
67
- StyleDictionary.registerFormat({
68
- name: 'css/variables',
69
- formatter: cssVariables,
70
- })
71
-
72
60
  StyleDictionary.registerFormat({
73
61
  name: 'javascript/esm',
74
62
  formatter: javascriptEsm,
@@ -0,0 +1,99 @@
1
+ import type {TransformedToken} from 'style-dictionary'
2
+ import StyleDictionary from 'style-dictionary'
3
+ import type {FormatterArguments} from 'style-dictionary/types/Format'
4
+ import {format} from 'prettier'
5
+ import type {LineFormatting} from 'style-dictionary/types/FormatHelpers'
6
+ const {fileHeader, formattedVariables} = StyleDictionary.formatHelpers
7
+
8
+ const wrapWithSelector = (css: string, selector: string | false): string => {
9
+ // return without selector
10
+ if (selector === false || selector.trim().length === 0) return css
11
+ // return with selector
12
+ return `${selector} { ${css} }`
13
+ }
14
+
15
+ export const cssAdvanced: StyleDictionary.Formatter = ({
16
+ dictionary: originalDictionary,
17
+ options = {
18
+ queries: [],
19
+ },
20
+ file,
21
+ platform,
22
+ }: FormatterArguments): string => {
23
+ // get options
24
+ const {outputReferences, descriptions} = options
25
+ // selector
26
+ const selector = file.options?.selector !== undefined ? file.options.selector : ':root'
27
+ // query extension property
28
+ const queryExtProp = file.options?.queryExtensionProperty || 'mediaQuery'
29
+ // get queries from file options
30
+ const queries = file.options?.queries || [
31
+ {
32
+ query: undefined,
33
+ matcher: () => true,
34
+ },
35
+ ]
36
+ // set formatting
37
+ const formatting: LineFormatting = {
38
+ commentStyle: descriptions ? 'long' : 'none',
39
+ }
40
+ // clone dictionary
41
+ const dictionary = {...originalDictionary}
42
+ // add prefix to tokens
43
+ if (platform.prefix) {
44
+ dictionary.allTokens = dictionary.allTokens.map(
45
+ token =>
46
+ ({
47
+ ...token,
48
+ name: `${platform.prefix}-${token.name}`,
49
+ path: [platform.prefix, ...token.path],
50
+ } as TransformedToken),
51
+ )
52
+ }
53
+ // get queries from tokens
54
+ for (const designToken of dictionary.allTokens) {
55
+ const query = designToken.$extensions?.[queryExtProp]
56
+ // early abort if query does not exist on token
57
+ if (!query) continue
58
+ // if query exists already from other token
59
+ const currentQueryIndex = queries.findIndex((q: {query: string; matcher: () => boolean}) => q.query === query)
60
+
61
+ // if query exists
62
+ if (currentQueryIndex > -1) {
63
+ queries[currentQueryIndex] = {
64
+ ...queries[currentQueryIndex],
65
+ matcher: (token: TransformedToken) =>
66
+ queries[currentQueryIndex].matcher(token) ||
67
+ token.$extensions[queryExtProp] === queries[currentQueryIndex].query,
68
+ }
69
+ }
70
+ // if query does not exist
71
+ else {
72
+ queries.push({
73
+ query,
74
+ matcher: (token: TransformedToken) => token.$extensions?.[queryExtProp] === query,
75
+ })
76
+ }
77
+ }
78
+ // add file header
79
+ const output = [fileHeader({file})]
80
+ // add single theme css
81
+ for (const query of queries) {
82
+ const {query: queryString, matcher} = query
83
+ // filter tokens to only include the ones that pass the matcher
84
+ const filteredDictionary = {
85
+ ...dictionary,
86
+ allTokens: dictionary.allTokens.filter(matcher || (() => true)),
87
+ }
88
+ // early abort if no matches
89
+ if (!filteredDictionary.allTokens.length) continue
90
+ // add tokens into root
91
+ const css = formattedVariables({format: 'css', dictionary: filteredDictionary, outputReferences, formatting})
92
+ // wrap css
93
+ const cssWithSelector = wrapWithSelector(css, query.selector !== undefined ? query.selector : selector)
94
+ // add css with or without query
95
+ output.push(queryString ? `${queryString} { ${cssWithSelector} }` : cssWithSelector)
96
+ }
97
+ // return prettified
98
+ return format(output.join('\n'), {parser: 'css', printWidth: 500})
99
+ }
@@ -1,7 +1,5 @@
1
- export {cssThemed} from './cssThemed'
2
1
  export {cssCustomMedia} from './cssCustomMedia'
3
- export {cssWrapMediaQuery} from './cssWrapMediaQuery'
4
- export {cssVariables} from './cssVariables'
2
+ export {cssAdvanced} from './cssAdvanced'
5
3
  export {jsonFigma} from './jsonFigma'
6
4
  export {javascriptCommonJs} from './javascriptCommonJs'
7
5
  export {javascriptEsm} from './javascriptEsm'
@@ -1,23 +1,27 @@
1
1
  import {isFromFile, isSource} from '../filters'
2
2
  import type StyleDictionary from 'style-dictionary'
3
3
  import type {PlatformInitializer} from '../types/PlatformInitializer'
4
+ import type {TransformedToken} from 'style-dictionary'
4
5
 
5
- const getCssSelectors = (outputFile: string): {selector: string; selectorLight: string; selectorDark: string} => {
6
+ const getCssSelectors = (outputFile: string) => {
6
7
  // check for dark in the beginning of the output filename
7
8
  const lastSlash = outputFile.lastIndexOf('/')
8
9
  const outputBasename = outputFile.substring(lastSlash + 1, outputFile.indexOf('.'))
9
10
  const themeName = outputBasename.replace(/-/g, '_')
10
11
  const mode = outputBasename.substring(0, 4) === 'dark' ? 'dark' : 'light'
11
12
 
12
- return {
13
- selector: `[data-color-mode="${mode}"][data-${mode}-theme="${themeName}"], [data-color-mode="${mode}"][data-${mode}-theme="${themeName}"] ::backdrop`,
14
- selectorLight: `[data-color-mode="auto"][data-light-theme="${themeName}"], [data-color-mode="auto"][data-light-theme="${themeName}"] ::backdrop`,
15
- selectorDark: `[data-color-mode="auto"][data-dark-theme="${themeName}"], [data-color-mode="auto"][data-dark-theme="${themeName}"] ::backdrop`,
16
- }
13
+ return [
14
+ {
15
+ selector: `[data-color-mode="${mode}"][data-${mode}-theme="${themeName}"], [data-color-mode="${mode}"][data-${mode}-theme="${themeName}"] ::backdrop, [data-color-mode="auto"][data-light-theme="${themeName}"], [data-color-mode="auto"][data-light-theme="${themeName}"] ::backdrop`,
16
+ },
17
+ {
18
+ query: '@media (prefers-color-scheme: dark)',
19
+ selector: `[data-color-mode="auto"][data-dark-theme="${themeName}"], [data-color-mode="auto"][data-dark-theme="${themeName}"] ::backdrop`,
20
+ },
21
+ ]
17
22
  }
18
23
 
19
24
  export const css: PlatformInitializer = (outputFile, prefix, buildPath, options): StyleDictionary.Platform => {
20
- const {selector, selectorLight, selectorDark} = getCssSelectors(outputFile)
21
25
  return {
22
26
  prefix,
23
27
  buildPath,
@@ -40,21 +44,19 @@ export const css: PlatformInitializer = (outputFile, prefix, buildPath, options)
40
44
  files: [
41
45
  {
42
46
  destination: `${outputFile}`,
43
- format: `css/themed`,
47
+ format: `css/advanced`,
44
48
  filter: token => isSource(token) && options?.themed === true,
45
49
  options: {
46
50
  showFileHeader: false,
47
51
  outputReferences: false,
48
52
  descriptions: false,
49
- selector,
50
- selectorLight,
51
- selectorDark,
53
+ queries: getCssSelectors(outputFile),
52
54
  ...options?.options,
53
55
  },
54
56
  },
55
57
  {
56
58
  destination: `${outputFile}`,
57
- format: `css/variables`,
59
+ format: `css/advanced`,
58
60
  filter: token => isSource(token) && options?.themed !== true,
59
61
  options: {
60
62
  showFileHeader: false,
@@ -72,7 +74,7 @@ export const css: PlatformInitializer = (outputFile, prefix, buildPath, options)
72
74
  },
73
75
  {
74
76
  destination: `${outputFile}`,
75
- format: `css/wrapMediaQuery`,
77
+ format: `css/advanced`,
76
78
  filter: token =>
77
79
  isSource(token) &&
78
80
  isFromFile(token, [
@@ -82,10 +84,16 @@ export const css: PlatformInitializer = (outputFile, prefix, buildPath, options)
82
84
  options: {
83
85
  descriptions: false,
84
86
  showFileHeader: false,
85
- mediaQuery: {
86
- 'css/functional/size/size-fine.css': '(pointer: fine)',
87
- 'css/functional/size/size-coarse.css': '(pointer: coarse)',
88
- },
87
+ queries: [
88
+ {
89
+ query: '@media (pointer: fine)',
90
+ matcher: (token: TransformedToken) => token.path.includes('size-fine'),
91
+ },
92
+ {
93
+ query: '@media (pointer: coarse)',
94
+ matcher: (token: TransformedToken) => token.path.includes('size-coarse'),
95
+ },
96
+ ],
89
97
  },
90
98
  },
91
99
  ],
@@ -1,35 +0,0 @@
1
- import StyleDictionary from 'style-dictionary'
2
- import type {FormatterArguments} from 'style-dictionary/types/Format'
3
- import {format} from 'prettier'
4
- import type {LineFormatting} from 'style-dictionary/types/FormatHelpers'
5
- const {fileHeader, formattedVariables} = StyleDictionary.formatHelpers
6
-
7
- /**
8
- * @description Converts `StyleDictionary.dictionary.tokens` to css with prefers dark and light section
9
- * @param arguments [FormatterArguments](https://github.com/amzn/style-dictionary/blob/main/types/Format.d.ts)
10
- * @param arguments.options outputReferences `boolean`, selector `string`, selectorLight `string`, selectorDark `string`
11
- * @returns formatted `string`
12
- */
13
- export const cssThemed: StyleDictionary.Formatter = ({dictionary, options = {}, file}: FormatterArguments) => {
14
- const {selector, selectorLight, selectorDark} = options
15
- const {outputReferences, descriptions} = options
16
- const formatting: LineFormatting = {
17
- commentStyle: descriptions ? 'long' : 'none',
18
- }
19
- // add file header
20
- const output = [fileHeader({file})]
21
- // add single theme css
22
- output.push(`${selector || ':root'}${selectorLight ? `, ${selectorLight}` : ''}{
23
- ${formattedVariables({format: 'css', dictionary, outputReferences, formatting})}
24
- }`)
25
- // add auto dark theme css
26
- if (selectorDark) {
27
- output.push(`@media (prefers-color-scheme: dark) {
28
- ${selectorDark} {
29
- ${formattedVariables({format: 'css', dictionary, outputReferences, formatting})}
30
- }
31
- }`)
32
- }
33
- // return prettified
34
- return format(output.join('\n'), {parser: 'css', printWidth: 500})
35
- }
@@ -1,25 +0,0 @@
1
- import StyleDictionary from 'style-dictionary'
2
- import type {FormatterArguments} from 'style-dictionary/types/Format'
3
- import type {LineFormatting} from 'style-dictionary/types/FormatHelpers'
4
- const {fileHeader, formattedVariables} = StyleDictionary.formatHelpers
5
-
6
- /**
7
- * @description Converts `StyleDictionary.dictionary.tokens` to csssection
8
- * @param arguments [FormatterArguments](https://github.com/amzn/style-dictionary/blob/main/types/Format.d.ts)
9
- * @param arguments.options outputReferences `boolean`, selector `string`
10
- * @returns formatted `string`
11
- */
12
- export const cssVariables: StyleDictionary.Formatter = ({dictionary, options = {}, file}: FormatterArguments) => {
13
- const selector = options.selector ? options.selector : `:root`
14
- const {outputReferences, descriptions} = options
15
- const formatting: LineFormatting = {
16
- commentStyle: descriptions ? 'long' : 'none',
17
- }
18
-
19
- return `${fileHeader({file})}${selector} {\n${formattedVariables({
20
- format: 'css',
21
- dictionary,
22
- outputReferences,
23
- formatting,
24
- })}\n}\n`
25
- }
@@ -1,29 +0,0 @@
1
- import StyleDictionary from 'style-dictionary'
2
- import type {FormatterArguments} from 'style-dictionary/types/Format'
3
- import {format} from 'prettier'
4
- import type {LineFormatting} from 'style-dictionary/types/FormatHelpers'
5
- const {fileHeader, formattedVariables} = StyleDictionary.formatHelpers
6
-
7
- /**
8
- * @description Converts `StyleDictionary.dictionary.tokens` to css with @custom-media
9
- * @param arguments [FormatterArguments](https://github.com/amzn/style-dictionary/blob/main/types/Format.d.ts)
10
- * @returns formatted `string`
11
- */
12
- export const cssWrapMediaQuery: StyleDictionary.Formatter = ({dictionary, options, file}: FormatterArguments) => {
13
- const {outputReferences, descriptions} = options
14
- const formatting: LineFormatting = {
15
- commentStyle: descriptions ? 'long' : 'none',
16
- }
17
- // get specific media query or use screen
18
- const mediaQuery = options.mediaQuery?.[file.destination] || 'screen'
19
- // add file header
20
- const output = [fileHeader({file})]
21
- // add meadia query
22
- output.push(`@media ${mediaQuery} {\n:root {`)
23
- // add tokens
24
- output.push(formattedVariables({format: 'css', dictionary, outputReferences, formatting}))
25
- // close media query
26
- output.push(`}\n}`)
27
- // return prettified
28
- return format(output.join('\n'), {parser: 'css', printWidth: 500})
29
- }