@_linked/cli 1.4.5 → 1.5.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#36](https://github.com/linked-cm/cli/pull/36) [`fc37baa`](https://github.com/linked-cm/cli/commit/fc37baa54874d64349622b56b05d14f691bafb1c) Thanks [@flyon](https://github.com/flyon)! - The components-showcase page (`/page1`) is now a public route by default — the template doesn't wire up an authentication provider out of the box, so `requireAuth` would just hide the page behind a redirect to a non-functional signin. The `requireAuth: true` line is now commented out with a note pointing readers to `@_linked/auth` when they want to add it.
8
+
9
+ Top-of-file comment in `Page1.tsx` updated to match.
10
+
11
+ ## 1.5.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#34](https://github.com/linked-cm/cli/pull/34) [`4138d8f`](https://github.com/linked-cm/cli/commit/4138d8fbbee6c5def8538d2297bedd5c0ed3e4e7) Thanks [@flyon](https://github.com/flyon)! - Template visual upgrade: animated background + primitives showcase.
16
+
17
+ **Animated background.** `App.module.css` now renders a fixed-position layer underneath all content with three soft radial-gradient blobs that drift and gently pulse on a 22s loop. Brand-colored via `--color-primary-300` / `--color-secondary-300` / `--color-tertiary-200`, so the look re-tints automatically when an app overrides theme tokens. Honors `prefers-reduced-motion: reduce`.
18
+
19
+ **Protected page** (`/page1`) reworked into a `@_linked/primitives` showcase, organized into `Tabs` (Forms / Display / Buttons). Exercises `Button` (variants, colors, sizes), `Input`, `Switch`, `Checkbox`, `RadioGroup`, `Slider`, `Progress`, `Avatar`, `Label`, `Separator` — useful both as a visual smoke-test of the active theme and as starter code showing how to reach for each primitive.
20
+
21
+ `@_linked/primitives` added as a template dep (`^1.0.6`).
22
+
3
23
  ## 1.4.5
4
24
 
5
25
  ### Patch Changes
@@ -42,6 +42,7 @@
42
42
  "@_linked/server-utils": "^1.0.6",
43
43
  "@_linked/schema": "^1.0.6",
44
44
  "@_linked/fuseki": "^2.0",
45
+ "@_linked/primitives": "^1.0.6",
45
46
  "@_linked/react": "^1.3",
46
47
  "react": "^18.2",
47
48
  "react-dom": "^18.2",
@@ -5,10 +5,61 @@
5
5
  background: var(--bg-page);
6
6
  color: var(--color-gray-900);
7
7
  margin: 0;
8
+ overflow-x: hidden;
9
+ }
10
+
11
+ /* Animated background: soft radial-gradient "blobs" drifting and pulsing
12
+ underneath the content. Brand-colored via @_linked/css tokens — recolors
13
+ automatically when --color-primary-* / --color-secondary-* change in theme.css. */
14
+ :global(body)::before {
15
+ content: '';
16
+ position: fixed;
17
+ inset: 0;
18
+ z-index: -1;
19
+ pointer-events: none;
20
+ background:
21
+ radial-gradient(
22
+ circle at 18% 22%,
23
+ var(--color-primary-300) 0%,
24
+ transparent 38%
25
+ ),
26
+ radial-gradient(
27
+ circle at 82% 76%,
28
+ var(--color-secondary-300) 0%,
29
+ transparent 42%
30
+ ),
31
+ radial-gradient(
32
+ circle at 55% 58%,
33
+ var(--color-tertiary-200) 0%,
34
+ transparent 50%
35
+ );
36
+ opacity: 0.35;
37
+ filter: blur(40px);
38
+ animation: drift 22s ease-in-out infinite;
39
+ }
40
+
41
+ @keyframes drift {
42
+ 0%,
43
+ 100% {
44
+ transform: translate3d(0, 0, 0) scale(1);
45
+ }
46
+ 33% {
47
+ transform: translate3d(-3%, 2%, 0) scale(1.05);
48
+ }
49
+ 66% {
50
+ transform: translate3d(3%, -2%, 0) scale(0.97);
51
+ }
52
+ }
53
+
54
+ @media (prefers-reduced-motion: reduce) {
55
+ :global(body)::before {
56
+ animation: none;
57
+ }
8
58
  }
9
59
 
10
60
  .App {
11
61
  min-height: 100vh;
62
+ position: relative;
12
63
  }
13
64
 
14
65
  :global(h1) {
@@ -1,18 +1,102 @@
1
1
  @import '@_linked/css/package.css';
2
2
 
3
- .Card {
3
+ .Page {
4
+ display: flex;
5
+ flex-direction: column;
6
+ gap: --spacing(5);
7
+ }
8
+
9
+ .Header {
4
10
  background: var(--bg-card);
5
11
  border-radius: var(--radius-card);
6
12
  box-shadow: var(--shadow-card);
7
13
  padding: --spacing(6);
8
14
  }
9
15
 
10
- .Card h2 {
11
- margin: 0 0 --spacing(3);
16
+ .Header h2 {
17
+ margin: 0 0 --spacing(2);
12
18
  }
13
19
 
14
- .Card p {
20
+ .Header p {
15
21
  color: var(--color-gray-700);
16
22
  line-height: 1.5;
17
23
  margin: 0;
18
24
  }
25
+
26
+ .Header code {
27
+ background: var(--bg-section);
28
+ padding: 0 --spacing(1);
29
+ border-radius: var(--radius-element);
30
+ font-family: var(--font-mono);
31
+ font-size: 0.85em;
32
+ }
33
+
34
+ .Tabs {
35
+ background: var(--bg-card);
36
+ border-radius: var(--radius-card);
37
+ box-shadow: var(--shadow-card);
38
+ padding: --spacing(5);
39
+ }
40
+
41
+ .TabPanel {
42
+ display: grid;
43
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
44
+ gap: --spacing(4);
45
+ margin-top: --spacing(5);
46
+ }
47
+
48
+ .Card {
49
+ background: var(--bg-section);
50
+ border-radius: var(--radius-element);
51
+ padding: --spacing(4);
52
+ display: flex;
53
+ flex-direction: column;
54
+ gap: --spacing(3);
55
+ }
56
+
57
+ .Card h3 {
58
+ margin: 0;
59
+ font-size: 0.85rem;
60
+ font-weight: 600;
61
+ letter-spacing: 0.04em;
62
+ text-transform: uppercase;
63
+ color: var(--color-gray-600);
64
+ }
65
+
66
+ .Field {
67
+ display: flex;
68
+ flex-direction: column;
69
+ gap: --spacing(2);
70
+ }
71
+
72
+ .Stack {
73
+ display: flex;
74
+ flex-direction: column;
75
+ gap: --spacing(2);
76
+ }
77
+
78
+ .Row {
79
+ display: flex;
80
+ align-items: center;
81
+ gap: --spacing(2);
82
+ flex-wrap: wrap;
83
+ }
84
+
85
+ .ButtonRow {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: --spacing(2);
89
+ flex-wrap: wrap;
90
+ }
91
+
92
+ .AvatarRow {
93
+ display: flex;
94
+ gap: --spacing(3);
95
+ align-items: center;
96
+ }
97
+
98
+ .Hint {
99
+ color: var(--color-gray-600);
100
+ font-size: 0.875rem;
101
+ margin: 0;
102
+ }
@@ -1,15 +1,188 @@
1
+ // Components showcase — demonstrates a slice of @_linked/primitives against
2
+ // the active @_linked/css theme. Tweak tokens in src/theme.css to re-skin
3
+ // everything on this page. (To make the route sign-in-protected later, see
4
+ // the `requireAuth` line in src/routes.tsx.)
5
+ import React, { useState } from 'react';
1
6
  import { DefaultLayout } from '../layout/DefaultLayout';
7
+ import { Button } from '@_linked/primitives/components/Button';
8
+ import { Input } from '@_linked/primitives/components/Input';
9
+ import { Switch } from '@_linked/primitives/components/Switch';
10
+ import { Checkbox } from '@_linked/primitives/components/Checkbox';
11
+ import { Slider } from '@_linked/primitives/components/Slider';
12
+ import { Progress } from '@_linked/primitives/components/Progress';
13
+ import { Avatar } from '@_linked/primitives/components/Avatar';
14
+ import { Tabs } from '@_linked/primitives/components/Tabs';
15
+ import { RadioGroup } from '@_linked/primitives/components/RadioGroup';
16
+ import { Label } from '@_linked/primitives/components/Label';
17
+ import { Separator } from '@_linked/primitives/components/Separator';
2
18
  import style from './Page1.module.css';
3
19
 
4
20
  export default function Page1() {
21
+ const [progress, setProgress] = useState(60);
22
+ const [sliderValue, setSliderValue] = useState([40]);
23
+ const [checked, setChecked] = useState(true);
24
+ const [switchOn, setSwitchOn] = useState(true);
25
+ const [radio, setRadio] = useState('comfy');
26
+ const [text, setText] = useState('');
27
+
5
28
  return (
6
29
  <DefaultLayout>
7
- <div className={style.Card}>
8
- <h2>Page 1</h2>
9
- <p>
10
- A second route to show how navigation works. Edit{' '}
11
- <code>src/pages/Page1.tsx</code> to make this your own.
12
- </p>
30
+ <div className={style.Page}>
31
+ <header className={style.Header}>
32
+ <h2>Components</h2>
33
+ <p>
34
+ A small tour of <code>@_linked/primitives</code> rendered against
35
+ the active <code>@_linked/css</code> theme. Tweak{' '}
36
+ <code>src/theme.css</code> tokens to re-skin every component on
37
+ this page.
38
+ </p>
39
+ </header>
40
+
41
+ <Tabs.Root defaultValue="forms" className={style.Tabs}>
42
+ <Tabs.List>
43
+ <Tabs.Trigger value="forms">Forms</Tabs.Trigger>
44
+ <Tabs.Trigger value="display">Display</Tabs.Trigger>
45
+ <Tabs.Trigger value="buttons">Buttons</Tabs.Trigger>
46
+ </Tabs.List>
47
+
48
+ <Tabs.Content value="forms" className={style.TabPanel}>
49
+ <section className={style.Card}>
50
+ <h3>Inputs</h3>
51
+ <div className={style.Field}>
52
+ <Label htmlFor="demo-name">Name</Label>
53
+ <Input
54
+ id="demo-name"
55
+ placeholder="Ada Lovelace"
56
+ value={text}
57
+ onChange={(e) => setText(e.target.value)}
58
+ />
59
+ </div>
60
+ <Separator />
61
+ <div className={style.Row}>
62
+ <Switch
63
+ checked={switchOn}
64
+ onCheckedChange={(v) => setSwitchOn(Boolean(v))}
65
+ />
66
+ <Label>Enable notifications</Label>
67
+ </div>
68
+ <div className={style.Row}>
69
+ <Checkbox
70
+ checked={checked}
71
+ onCheckedChange={(v) => setChecked(Boolean(v))}
72
+ />
73
+ <Label>I agree to the terms</Label>
74
+ </div>
75
+ </section>
76
+
77
+ <section className={style.Card}>
78
+ <h3>Density</h3>
79
+ <RadioGroup.Root
80
+ value={radio}
81
+ onValueChange={setRadio}
82
+ className={style.Stack}
83
+ >
84
+ <div className={style.Row}>
85
+ <RadioGroup.Item value="compact" id="r-compact" />
86
+ <Label htmlFor="r-compact">Compact</Label>
87
+ </div>
88
+ <div className={style.Row}>
89
+ <RadioGroup.Item value="comfy" id="r-comfy" />
90
+ <Label htmlFor="r-comfy">Comfortable</Label>
91
+ </div>
92
+ <div className={style.Row}>
93
+ <RadioGroup.Item value="spacious" id="r-spacious" />
94
+ <Label htmlFor="r-spacious">Spacious</Label>
95
+ </div>
96
+ </RadioGroup.Root>
97
+ </section>
98
+
99
+ <section className={style.Card}>
100
+ <h3>Slider</h3>
101
+ <Slider.Root
102
+ value={sliderValue}
103
+ onValueChange={setSliderValue}
104
+ min={0}
105
+ max={100}
106
+ step={1}
107
+ >
108
+ <Slider.Track>
109
+ <Slider.Range />
110
+ </Slider.Track>
111
+ <Slider.Thumb />
112
+ </Slider.Root>
113
+ <p className={style.Hint}>Value: {sliderValue[0]}</p>
114
+ </section>
115
+ </Tabs.Content>
116
+
117
+ <Tabs.Content value="display" className={style.TabPanel}>
118
+ <section className={style.Card}>
119
+ <h3>Avatar</h3>
120
+ <div className={style.AvatarRow}>
121
+ <Avatar.Root>
122
+ <Avatar.Fallback>AL</Avatar.Fallback>
123
+ </Avatar.Root>
124
+ <Avatar.Root>
125
+ <Avatar.Fallback>GH</Avatar.Fallback>
126
+ </Avatar.Root>
127
+ <Avatar.Root>
128
+ <Avatar.Fallback>RV</Avatar.Fallback>
129
+ </Avatar.Root>
130
+ </div>
131
+ </section>
132
+
133
+ <section className={style.Card}>
134
+ <h3>Progress</h3>
135
+ <Progress.Root value={progress} />
136
+ <div className={style.Row}>
137
+ <Button
138
+ size="small"
139
+ variant="outline"
140
+ onClick={() => setProgress((p) => Math.max(0, p - 10))}
141
+ >
142
+ −10
143
+ </Button>
144
+ <Button
145
+ size="small"
146
+ variant="outline"
147
+ onClick={() => setProgress((p) => Math.min(100, p + 10))}
148
+ >
149
+ +10
150
+ </Button>
151
+ <span className={style.Hint}>{progress}%</span>
152
+ </div>
153
+ </section>
154
+ </Tabs.Content>
155
+
156
+ <Tabs.Content value="buttons" className={style.TabPanel}>
157
+ <section className={style.Card}>
158
+ <h3>Variants</h3>
159
+ <div className={style.ButtonRow}>
160
+ <Button variant="solid">Solid</Button>
161
+ <Button variant="outline">Outline</Button>
162
+ <Button variant="ghost">Ghost</Button>
163
+ <Button variant="link">Link</Button>
164
+ </div>
165
+ </section>
166
+
167
+ <section className={style.Card}>
168
+ <h3>Colors</h3>
169
+ <div className={style.ButtonRow}>
170
+ <Button color="primary">Primary</Button>
171
+ <Button color="secondary">Secondary</Button>
172
+ <Button color="tertiary">Tertiary</Button>
173
+ </div>
174
+ </section>
175
+
176
+ <section className={style.Card}>
177
+ <h3>Sizes</h3>
178
+ <div className={style.ButtonRow}>
179
+ <Button size="small">Small</Button>
180
+ <Button size="medium">Medium</Button>
181
+ <Button size="large">Large</Button>
182
+ </div>
183
+ </section>
184
+ </Tabs.Content>
185
+ </Tabs.Root>
13
186
  </div>
14
187
  </DefaultLayout>
15
188
  );
@@ -34,9 +34,11 @@ export const ROUTES: RoutesConfig = {
34
34
  component: lazy(
35
35
  () => import(/* webpackChunkName: "page1" */ './pages/Page1')
36
36
  ),
37
- label: 'Protected page',
38
- requireAuth: true,
37
+ label: 'Components',
39
38
  preloadChunks: ['page1'],
39
+ // To make this route sign-in-protected, uncomment the next line + wire up
40
+ // an authentication provider in App.tsx. See @_linked/auth for options.
41
+ // requireAuth: true,
40
42
  },
41
43
  signin: {
42
44
  path: '/signin',
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_linked/cli",
3
- "version": "1.4.5",
3
+ "version": "1.5.1",
4
4
  "description": "Command line tools for the @_linked/* packages and apps",
5
5
  "typesVersions": {
6
6
  "*": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_linked/cli",
3
- "version": "1.4.5",
3
+ "version": "1.5.1",
4
4
  "description": "Command line tools for the @_linked/* packages and apps",
5
5
  "typesVersions": {
6
6
  "*": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_linked/cli",
3
- "version": "1.4.5",
3
+ "version": "1.5.1",
4
4
  "description": "Command line tools for the @_linked/* packages and apps",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/esm/index.js",