@rolemodel/optics 0.2.3
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/.eslintrc.json +14 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +19 -0
- package/.github/pull_request_template.md +30 -0
- package/.github/workflows/linting.yml +38 -0
- package/.github/workflows/publish-storybook.yml +26 -0
- package/.github/workflows/release-package.yml +33 -0
- package/.prettierignore +0 -0
- package/.prettierrc.json +8 -0
- package/.storybook/ModeSwitcher.jsx +98 -0
- package/.storybook/documentation.scss +65 -0
- package/.storybook/main.js +10 -0
- package/.storybook/manager.js +22 -0
- package/.storybook/preview.js +12 -0
- package/.storybook/rolemodelTheme.js +10 -0
- package/.stylelintrc.json +15 -0
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/build_token_json.js +149 -0
- package/dist/css/optics.css +2586 -0
- package/dist/css/optics.css.map +1 -0
- package/dist/scss/addons/rails-modal-and-panel/index.scss +2 -0
- package/dist/scss/addons/rails-modal-and-panel/modal.scss +86 -0
- package/dist/scss/addons/rails-modal-and-panel/panel.scss +36 -0
- package/dist/scss/addons/tom-select.scss +77 -0
- package/dist/scss/components/alert.scss +158 -0
- package/dist/scss/components/badge.scss +80 -0
- package/dist/scss/components/button.scss +235 -0
- package/dist/scss/components/button_group.scss +35 -0
- package/dist/scss/components/card.scss +65 -0
- package/dist/scss/components/flash.scss +58 -0
- package/dist/scss/components/form.scss +178 -0
- package/dist/scss/components/icon.scss +109 -0
- package/dist/scss/components/index.scss +10 -0
- package/dist/scss/components/sidebar.scss +255 -0
- package/dist/scss/components/table.scss +132 -0
- package/dist/scss/core/base.scss +95 -0
- package/dist/scss/core/layout.scss +36 -0
- package/dist/scss/core/tokens/base_tokens.scss +251 -0
- package/dist/scss/core/tokens/dark_mode_tokens.scss +324 -0
- package/dist/scss/core/tokens/index.scss +3 -0
- package/dist/scss/core/tokens/scale_color_tokens.scss +303 -0
- package/dist/scss/core/utilities.scss +548 -0
- package/dist/scss/optics.scss +13 -0
- package/dist/scss/recipes/16six-sidebar.scss +97 -0
- package/dist/scss/recipes/domains-sidebar.scss +60 -0
- package/dist/tokens/tokens.json +391 -0
- package/package.json +80 -0
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"root": true,
|
|
3
|
+
"extends": ["standard", "prettier"],
|
|
4
|
+
"rules": {
|
|
5
|
+
"no-unused-vars": [
|
|
6
|
+
"warn",
|
|
7
|
+
{
|
|
8
|
+
"argsIgnorePattern": "^_", // Allow unused arguments starting with an underscore
|
|
9
|
+
"varsIgnorePattern": "^_", // Allow unused variables starting with an underscore
|
|
10
|
+
"ignoreRestSiblings": true
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a report to help us improve
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Describe the bug**
|
|
10
|
+
A clear and concise description of what the bug is.
|
|
11
|
+
|
|
12
|
+
**To Reproduce**
|
|
13
|
+
Steps to reproduce the behavior:
|
|
14
|
+
|
|
15
|
+
1. Go to '...'
|
|
16
|
+
2. Click on '....'
|
|
17
|
+
3. Scroll down to '....'
|
|
18
|
+
4. See error
|
|
19
|
+
|
|
20
|
+
**Expected behavior**
|
|
21
|
+
A clear and concise description of what you expected to happen.
|
|
22
|
+
|
|
23
|
+
**Screenshots**
|
|
24
|
+
If applicable, add screenshots to help explain your problem.
|
|
25
|
+
|
|
26
|
+
**Desktop (please complete the following information):**
|
|
27
|
+
|
|
28
|
+
- OS: [e.g. iOS]
|
|
29
|
+
- Browser [e.g. chrome, safari]
|
|
30
|
+
- Version [e.g. 22]
|
|
31
|
+
|
|
32
|
+
**Smartphone (please complete the following information):**
|
|
33
|
+
|
|
34
|
+
- Device: [e.g. iPhone6]
|
|
35
|
+
- OS: [e.g. iOS8.1]
|
|
36
|
+
- Browser [e.g. stock browser, safari]
|
|
37
|
+
- Version [e.g. 22]
|
|
38
|
+
|
|
39
|
+
**Additional context**
|
|
40
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for this project
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
**Is your feature request related to a problem? Please describe.**
|
|
10
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
11
|
+
|
|
12
|
+
**Describe the solution you'd like**
|
|
13
|
+
A clear and concise description of what you want to happen.
|
|
14
|
+
|
|
15
|
+
**Describe alternatives you've considered**
|
|
16
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
|
17
|
+
|
|
18
|
+
**Additional context**
|
|
19
|
+
Add any other context or screenshots about the feature request here.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Task
|
|
2
|
+
|
|
3
|
+
[TR #XXX]()
|
|
4
|
+
|
|
5
|
+
## Why?
|
|
6
|
+
|
|
7
|
+
Why were the changes needed? What issues were the changes addressing?
|
|
8
|
+
(Note: some changes may seem unrelated to the ticket, this is a great place to explain further.)
|
|
9
|
+
|
|
10
|
+
## What Changed
|
|
11
|
+
|
|
12
|
+
What changed in this PR?
|
|
13
|
+
|
|
14
|
+
- [ ] Change 1
|
|
15
|
+
- [ ] Change 2
|
|
16
|
+
- [ ] ...
|
|
17
|
+
|
|
18
|
+
## Sanity Check
|
|
19
|
+
|
|
20
|
+
- [ ] Have you updated any usage of changed tokens?
|
|
21
|
+
- [ ] Have you updated the docs with any component changes?
|
|
22
|
+
- [ ] Have you run linters?
|
|
23
|
+
- [ ] Have you run prettier?
|
|
24
|
+
- [ ] Have you tried building the css?
|
|
25
|
+
- [ ] Have you tried building storybook?
|
|
26
|
+
- [ ] Do you need to update the package version?
|
|
27
|
+
|
|
28
|
+
## Screenshots
|
|
29
|
+
|
|
30
|
+
If any UI changes need to be shown off, please add screenshots here.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# This workflow will do a clean installation of node dependencies, cache/restore them, and run linting
|
|
2
|
+
|
|
3
|
+
name: Linting CI
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: ['main']
|
|
8
|
+
pull_request:
|
|
9
|
+
branches: ['main']
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
name: Run linters and check build scripts
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- name: Checkout repository
|
|
17
|
+
uses: actions/checkout@v3
|
|
18
|
+
- name: Use Node.js
|
|
19
|
+
uses: actions/setup-node@v3
|
|
20
|
+
with:
|
|
21
|
+
node-version: '16.x'
|
|
22
|
+
cache: 'npm'
|
|
23
|
+
- name: Install
|
|
24
|
+
run: npm install
|
|
25
|
+
- name: Run ESLint
|
|
26
|
+
run: npm run lint:js
|
|
27
|
+
- name: Run Stylelint
|
|
28
|
+
run: npm run lint:css
|
|
29
|
+
- name: Run Prettier
|
|
30
|
+
run: npm run prettier-check
|
|
31
|
+
- name: Build CSS
|
|
32
|
+
run: npm run build:css
|
|
33
|
+
- name: Build SCSS
|
|
34
|
+
run: npm run build:scss
|
|
35
|
+
- name: Build Tokens
|
|
36
|
+
run: npm run build:tokens
|
|
37
|
+
- name: Build Storybook
|
|
38
|
+
run: npm run build-storybook
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: Build and Deploy Storybook Documentation
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [created]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build-and-deploy:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- name: Checkout 🛎️
|
|
12
|
+
uses: actions/checkout@v3
|
|
13
|
+
with:
|
|
14
|
+
persist-credentials: false
|
|
15
|
+
- name: Install and Build 🔧
|
|
16
|
+
run: | # Install npm packages and build the Storybook files
|
|
17
|
+
npm install
|
|
18
|
+
npm run build-storybook
|
|
19
|
+
- name: Deploy 🚀
|
|
20
|
+
uses: JamesIves/github-pages-deploy-action@3.6.2
|
|
21
|
+
with:
|
|
22
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
23
|
+
BRANCH: gh-pages # The branch the action should deploy to.
|
|
24
|
+
FOLDER: docs-build # The folder that the build-storybook script generates files.
|
|
25
|
+
CLEAN: true # Automatically remove deleted files from the deploy branch
|
|
26
|
+
TARGET_FOLDER: docs # The folder that we serve our Storybook files from
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Deploy to NPM and GHP
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build-npm:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v3
|
|
12
|
+
- uses: actions/setup-node@v3
|
|
13
|
+
with:
|
|
14
|
+
node-version: '16.x'
|
|
15
|
+
registry-url: 'https://registry.npmjs.org'
|
|
16
|
+
- run: npm ci
|
|
17
|
+
- run: npm run build
|
|
18
|
+
- run: npm publish --access public
|
|
19
|
+
env:
|
|
20
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
21
|
+
build-gph:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v3
|
|
25
|
+
- uses: actions/setup-node@v3
|
|
26
|
+
with:
|
|
27
|
+
node-version: '16.x'
|
|
28
|
+
registry-url: https://npm.pkg.github.com/
|
|
29
|
+
- run: npm ci
|
|
30
|
+
- run: npm run build
|
|
31
|
+
- run: npm publish --access public
|
|
32
|
+
env:
|
|
33
|
+
NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
package/.prettierignore
ADDED
|
File without changes
|
package/.prettierrc.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { Button } from '@storybook/components'
|
|
3
|
+
|
|
4
|
+
import { useGlobals } from '@storybook/api'
|
|
5
|
+
|
|
6
|
+
// Destructuring like:
|
|
7
|
+
// const [globals, setGlobals] = useGlobals()
|
|
8
|
+
// or
|
|
9
|
+
// setGlobals({ ...globals, themeMode: mode })
|
|
10
|
+
// is not working so I had to work around it.
|
|
11
|
+
|
|
12
|
+
const ModeButton = ({ children, mode, currentThemeMode, updateThemeMode }) => {
|
|
13
|
+
const hoverState = useState(false)
|
|
14
|
+
const hover = hoverState[0]
|
|
15
|
+
const setHover = hoverState[1]
|
|
16
|
+
|
|
17
|
+
const backgroundColor = () => {
|
|
18
|
+
if (hover) {
|
|
19
|
+
return 'rgba(30, 167, 253, 0.12)'
|
|
20
|
+
}
|
|
21
|
+
return currentThemeMode === mode ? 'rgba(30,167,253,0.07)' : 'transparent'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const textColor = () => {
|
|
25
|
+
if (hover) {
|
|
26
|
+
return '#1EA7FD'
|
|
27
|
+
}
|
|
28
|
+
return currentThemeMode === mode ? '#1EA7FD' : '#999'
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const buttonStyles = (mode) => {
|
|
32
|
+
return {
|
|
33
|
+
borderRadius: 0,
|
|
34
|
+
padding: 8,
|
|
35
|
+
color: textColor(),
|
|
36
|
+
backgroundColor: backgroundColor(),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<Button
|
|
42
|
+
onMouseEnter={() => setHover(true)}
|
|
43
|
+
onMouseLeave={() => setHover(false)}
|
|
44
|
+
style={buttonStyles(mode)}
|
|
45
|
+
onClick={() => updateThemeMode(mode)}
|
|
46
|
+
title={`Set canvas to ${mode} mode`}
|
|
47
|
+
>
|
|
48
|
+
{children}
|
|
49
|
+
</Button>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const ModeSwitcher = () => {
|
|
54
|
+
const globalState = useGlobals()
|
|
55
|
+
const globals = globalState[0]
|
|
56
|
+
const setGlobals = globalState[1]
|
|
57
|
+
|
|
58
|
+
const setCanvasDocumentThemeMode = (mode) => {
|
|
59
|
+
const frame = document.getElementById('storybook-preview-iframe')
|
|
60
|
+
|
|
61
|
+
if (frame) {
|
|
62
|
+
const frameDocument = frame.contentWindow.document
|
|
63
|
+
frameDocument.children[0].dataset.themeMode = mode
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const updateThemeMode = (mode) => {
|
|
68
|
+
setCanvasDocumentThemeMode(mode)
|
|
69
|
+
globals.themeMode = mode
|
|
70
|
+
setGlobals(globals)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!globals.themeMode) {
|
|
74
|
+
updateThemeMode('light')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const containerStyles = () => {
|
|
78
|
+
return {
|
|
79
|
+
border: '1px solid rgb(0 0 0 / 10%)',
|
|
80
|
+
margin: 5,
|
|
81
|
+
borderRadius: '3em',
|
|
82
|
+
overflow: 'hidden',
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div style={containerStyles()}>
|
|
88
|
+
<ModeButton mode="light" currentThemeMode={globals.themeMode} updateThemeMode={updateThemeMode}>
|
|
89
|
+
Light
|
|
90
|
+
</ModeButton>
|
|
91
|
+
<ModeButton mode="dark" currentThemeMode={globals.themeMode} updateThemeMode={updateThemeMode}>
|
|
92
|
+
Dark
|
|
93
|
+
</ModeButton>
|
|
94
|
+
</div>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export default ModeSwitcher
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
@import './src/optics.scss';
|
|
2
|
+
|
|
3
|
+
@keyframes transitionDemo {
|
|
4
|
+
from {
|
|
5
|
+
background-color: var(--rm-color-white);
|
|
6
|
+
color: var(--rm-color-black);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
to {
|
|
10
|
+
background-color: var(--rm-color-primary-base);
|
|
11
|
+
color: var(--rm-color-primary-on-base);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.transition-demo {
|
|
16
|
+
display: inline-block;
|
|
17
|
+
|
|
18
|
+
background-color: var(--rm-color-primary-base);
|
|
19
|
+
color: var(--rm-color-primary-on-base);
|
|
20
|
+
|
|
21
|
+
padding: var(--rm-space-medium);
|
|
22
|
+
|
|
23
|
+
animation-name: transitionDemo;
|
|
24
|
+
animation-duration: var(--rm-transition-input);
|
|
25
|
+
animation-iteration-count: 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.transition-demo--input {
|
|
29
|
+
animation-duration: var(--rm-transition-input);
|
|
30
|
+
}
|
|
31
|
+
.transition-demo--navigation {
|
|
32
|
+
animation-duration: var(--rm-transition-navigation);
|
|
33
|
+
}
|
|
34
|
+
.transition-demo--sidebar {
|
|
35
|
+
animation-duration: var(--rm-transition-sidebar);
|
|
36
|
+
}
|
|
37
|
+
.transition-demo--modal {
|
|
38
|
+
animation-duration: var(--rm-transition-modal);
|
|
39
|
+
}
|
|
40
|
+
.transition-demo--panel {
|
|
41
|
+
animation-duration: var(--rm-transition-panel);
|
|
42
|
+
}
|
|
43
|
+
.transition-demo--flash {
|
|
44
|
+
animation-duration: var(--rm-transition-flash);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.flash--demo {
|
|
48
|
+
position: relative;
|
|
49
|
+
animation: none;
|
|
50
|
+
top: 0;
|
|
51
|
+
right: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@import './src/recipes/domains-sidebar.scss';
|
|
55
|
+
@import './src/recipes/16six-sidebar.scss';
|
|
56
|
+
|
|
57
|
+
.background-primary-plus-four {
|
|
58
|
+
background-color: var(--rm-color-primary-plus-four);
|
|
59
|
+
color: var(--rm-color-primary-on-plus-four);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.background-primary-plus-seven {
|
|
63
|
+
background-color: var(--rm-color-primary-plus-seven);
|
|
64
|
+
color: var(--rm-color-primary-on-plus-seven);
|
|
65
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
|
3
|
+
addons: [
|
|
4
|
+
'@storybook/addon-links',
|
|
5
|
+
'@storybook/addon-essentials',
|
|
6
|
+
'@storybook/addon-interactions',
|
|
7
|
+
'@storybook/preset-scss',
|
|
8
|
+
],
|
|
9
|
+
framework: '@storybook/html',
|
|
10
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { addons, types } from '@storybook/addons'
|
|
3
|
+
import rolemodelTheme from './rolemodelTheme'
|
|
4
|
+
|
|
5
|
+
import { useGlobals } from '@storybook/api' // For some reason this is needed here. ModeSwitcher won't work without it.
|
|
6
|
+
|
|
7
|
+
import ModeSwitcher from './ModeSwitcher'
|
|
8
|
+
|
|
9
|
+
addons.register('rolemodel/toolbar', () => {
|
|
10
|
+
addons.add('rolemodel-toolbar-addon/toolbar', {
|
|
11
|
+
title: 'Control to switch theme mode',
|
|
12
|
+
//👇 Sets the type of UI element in Storybook
|
|
13
|
+
type: types.TOOL,
|
|
14
|
+
//👇 Shows the Toolbar UI element if either the Canvas or Docs tab is active
|
|
15
|
+
match: ({ viewMode }) => !!(viewMode && viewMode.match(/^(story|docs)$/)),
|
|
16
|
+
render: () => <ModeSwitcher />,
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
addons.setConfig({
|
|
21
|
+
theme: rolemodelTheme,
|
|
22
|
+
})
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const parameters = {
|
|
2
|
+
actions: { argTypesRegex: '^on[A-Z].*' },
|
|
3
|
+
controls: {
|
|
4
|
+
matchers: {
|
|
5
|
+
color: /(background|color)$/i,
|
|
6
|
+
date: /Date$/,
|
|
7
|
+
},
|
|
8
|
+
},
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
import '!style-loader!css-loader!sass-loader!../src/optics.scss'
|
|
12
|
+
import '!style-loader!css-loader!sass-loader!./documentation.scss'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { create } from '@storybook/theming'
|
|
2
|
+
|
|
3
|
+
export default create({
|
|
4
|
+
base: 'light',
|
|
5
|
+
brandTitle: 'Optics, a RoleModel Design System',
|
|
6
|
+
brandUrl: 'https://docs.optics.rolemodel.design/',
|
|
7
|
+
brandImage:
|
|
8
|
+
'https://rolemodelsoftware.com/assets/rolemodel-logo--blue-5b7cee4303f5b115050586117bad8960640884812d1d51ee4b58817598c896da.svg',
|
|
9
|
+
brandTarget: '_self',
|
|
10
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": ["stylelint-config-standard-scss", "stylelint-config-idiomatic-order", "stylelint-config-prettier-scss"],
|
|
3
|
+
"plugins": ["stylelint-scss", "stylelint-prettier"],
|
|
4
|
+
"overrides": [
|
|
5
|
+
{
|
|
6
|
+
"files": ["**/*.scss"],
|
|
7
|
+
"customSyntax": "postcss-scss"
|
|
8
|
+
}
|
|
9
|
+
],
|
|
10
|
+
"rules": {
|
|
11
|
+
"prettier/prettier": true,
|
|
12
|
+
"custom-property-pattern": ["(?<=rm-)", { "message": "CSS variables should be prefixed with rm-" }],
|
|
13
|
+
"selector-class-pattern": null
|
|
14
|
+
}
|
|
15
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 RoleModel Software
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Optics, a RoleModel Design System
|
|
2
|
+
|
|
3
|
+
[](https://github.com/RoleModel/optics/actions/workflows/linting.yml)
|
|
4
|
+
|
|
5
|
+
Optics is an scss package that provides base styles and components that can be integrated and customized in a variety of projects.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
### NPM
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @rolemodel/optics
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Yarn
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
yarn add @rolemodel/optics
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Import
|
|
22
|
+
|
|
23
|
+
If you are using webpack to compile, you can add this import to the top of your root level `scss` file.
|
|
24
|
+
|
|
25
|
+
```scss
|
|
26
|
+
@import '@rolemodel/optics';
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If you are using a different compiler such as Dart Sass, you may need to reference the scss file directly.
|
|
30
|
+
|
|
31
|
+
```scss
|
|
32
|
+
@import '@rolemodel/optics/dist/scss/optics';
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Documentation
|
|
36
|
+
|
|
37
|
+
We use [Storybook](https://storybook.js.org/docs/html/get-started/introduction) as a way to provide informative and interactive documentation.
|
|
38
|
+
|
|
39
|
+
It can be found here [Optics Documentation](https://docs.optics.rolemodel.design/)
|
|
40
|
+
|
|
41
|
+
## Tokens
|
|
42
|
+
|
|
43
|
+
Tokens are defined in `src/core/tokens`
|
|
44
|
+
|
|
45
|
+
- All core tokens are defined in `src/core/tokens/base_tokens.scss`
|
|
46
|
+
- Basic color tokens are defined in `src/core/tokens/example_color_tokens.scss`
|
|
47
|
+
- Color scale tokens are defined in `src/core/tokens/scale_color_tokens.scss`
|
|
48
|
+
- Alert color tokens are defined in `src/core/tokens/alert_color_tokens.scss`
|
|
49
|
+
- Dark mode tokens are defined in `src/core/tokens/dark_mode_tokens.scss`
|
|
50
|
+
|
|
51
|
+
There are also a few component specific tokens that are defined in their respective component file, but those are not indented to be global or used outside of that file.
|
|
52
|
+
|
|
53
|
+
There is a JSON file in `docs/token_structure.json` that lists all the current tokens in one place and shows how the names indicate organization.
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const path = require('node:path')
|
|
3
|
+
|
|
4
|
+
function isHyphenated(keys, length = 2) {
|
|
5
|
+
return HYPHENATED_WORDS.concat(HYPHENATED_LUMINOSITIES).includes(keys.slice(0, length).join('-'))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const HYPHENATED_WORDS = [
|
|
9
|
+
'z-index',
|
|
10
|
+
'neutral-variant',
|
|
11
|
+
'on-background',
|
|
12
|
+
'line-height',
|
|
13
|
+
'letter-spacing',
|
|
14
|
+
'scale-unit',
|
|
15
|
+
'input-height',
|
|
16
|
+
'width-large',
|
|
17
|
+
'width-x-large',
|
|
18
|
+
'card-outline',
|
|
19
|
+
'x-small',
|
|
20
|
+
'2x-small',
|
|
21
|
+
'3x-small',
|
|
22
|
+
'4x-small',
|
|
23
|
+
'5x-small',
|
|
24
|
+
'x-large',
|
|
25
|
+
'2x-large',
|
|
26
|
+
'3x-large',
|
|
27
|
+
'4x-large',
|
|
28
|
+
'5x-large',
|
|
29
|
+
'extra-light',
|
|
30
|
+
'extra-bold',
|
|
31
|
+
'semi-bold',
|
|
32
|
+
'dialog-backdrop',
|
|
33
|
+
'dialog-content',
|
|
34
|
+
'alert-group',
|
|
35
|
+
'on-minus-one',
|
|
36
|
+
'on-minus-two',
|
|
37
|
+
'on-minus-three',
|
|
38
|
+
'on-minus-four',
|
|
39
|
+
'on-minus-five',
|
|
40
|
+
'on-minus-six',
|
|
41
|
+
'on-minus-seven',
|
|
42
|
+
'on-minus-eight',
|
|
43
|
+
'on-minus-max',
|
|
44
|
+
'on-plus-one',
|
|
45
|
+
'on-plus-two',
|
|
46
|
+
'on-plus-three',
|
|
47
|
+
'on-plus-four',
|
|
48
|
+
'on-plus-five',
|
|
49
|
+
'on-plus-six',
|
|
50
|
+
'on-plus-seven',
|
|
51
|
+
'on-plus-eight',
|
|
52
|
+
'on-plus-max',
|
|
53
|
+
'minus-one',
|
|
54
|
+
'minus-two',
|
|
55
|
+
'minus-three',
|
|
56
|
+
'minus-four',
|
|
57
|
+
'minus-five',
|
|
58
|
+
'minus-six',
|
|
59
|
+
'minus-seven',
|
|
60
|
+
'minus-eight',
|
|
61
|
+
'minus-max',
|
|
62
|
+
'plus-one',
|
|
63
|
+
'plus-two',
|
|
64
|
+
'plus-three',
|
|
65
|
+
'plus-four',
|
|
66
|
+
'plus-five',
|
|
67
|
+
'plus-six',
|
|
68
|
+
'plus-seven',
|
|
69
|
+
'plus-eight',
|
|
70
|
+
'plus-max',
|
|
71
|
+
'on-base',
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
// This is used in the isHyphenated method so that any key of luminosity-x returns true.
|
|
75
|
+
const HYPHENATED_LUMINOSITIES = [...Array(101).keys()].map((luminosity) => `luminosity-${luminosity}`)
|
|
76
|
+
|
|
77
|
+
function splitKey(key) {
|
|
78
|
+
let keys = key.slice(2).split('-')
|
|
79
|
+
return keys
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function addToJson(keys, data, value) {
|
|
83
|
+
let currentKey, remainingKeys
|
|
84
|
+
|
|
85
|
+
if (isHyphenated(keys, 2)) {
|
|
86
|
+
;[currentKey, remainingKeys] = [keys.slice(0, 2).join('-'), keys.slice(2)]
|
|
87
|
+
} else if (isHyphenated(keys, 3)) {
|
|
88
|
+
;[currentKey, remainingKeys] = [keys.join('-'), keys.slice(3)]
|
|
89
|
+
} else {
|
|
90
|
+
;[currentKey, ...remainingKeys] = keys
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
data[currentKey] = data[currentKey] ?? {}
|
|
94
|
+
|
|
95
|
+
switch (remainingKeys.length) {
|
|
96
|
+
case 0:
|
|
97
|
+
data[currentKey] = value
|
|
98
|
+
break
|
|
99
|
+
case 1:
|
|
100
|
+
data[currentKey][remainingKeys[0]] = value
|
|
101
|
+
break
|
|
102
|
+
default:
|
|
103
|
+
data[currentKey] = addToJson(remainingKeys, data[currentKey], value)
|
|
104
|
+
break
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return data
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
const arguments = {}
|
|
112
|
+
process.argv.forEach((argument) => {
|
|
113
|
+
const values = argument.slice(2).split('=')
|
|
114
|
+
if (values.length === 2) {
|
|
115
|
+
arguments[values[0]] = values[1]
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const source = arguments['source'] || 'src/core/tokens'
|
|
120
|
+
const output = arguments['output'] || './dist/tokens'
|
|
121
|
+
const outputPath = path.dirname(output)
|
|
122
|
+
const outputFile = path.basename(output)
|
|
123
|
+
|
|
124
|
+
if (!fs.existsSync(outputPath)) {
|
|
125
|
+
fs.mkdirSync(outputPath, { recursive: true })
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fs.readdir(source, { withFileTypes: true }, (_errors, files) => {
|
|
129
|
+
let variables = {}
|
|
130
|
+
files
|
|
131
|
+
.filter(
|
|
132
|
+
(directoryEntry) =>
|
|
133
|
+
directoryEntry.isFile() &&
|
|
134
|
+
directoryEntry.name !== 'dark_mode_tokens.scss' &&
|
|
135
|
+
directoryEntry.name !== 'index.scss'
|
|
136
|
+
)
|
|
137
|
+
.forEach((directoryEntry) => {
|
|
138
|
+
const fileContents = fs.readFileSync(`${source}/${directoryEntry.name}`)
|
|
139
|
+
const matches = fileContents.toString().match(/^\s*--.*?(?=;)/gm)
|
|
140
|
+
matches.forEach((match) => {
|
|
141
|
+
const [key, value] = match.split(':')
|
|
142
|
+
variables = addToJson(splitKey(key.trim()), variables, value.trim())
|
|
143
|
+
})
|
|
144
|
+
})
|
|
145
|
+
fs.writeFileSync(`${outputPath}/${outputFile}`, JSON.stringify(variables, null, '\t'))
|
|
146
|
+
})
|
|
147
|
+
} catch (err) {
|
|
148
|
+
console.log(err)
|
|
149
|
+
}
|