@_linked/cli 1.4.4 → 1.5.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#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.
8
+
9
+ **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`.
10
+
11
+ **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.
12
+
13
+ `@_linked/primitives` added as a template dep (`^1.0.6`).
14
+
15
+ ## 1.4.5
16
+
17
+ ### Patch Changes
18
+
19
+ - [#32](https://github.com/linked-cm/cli/pull/32) [`2f0b4d3`](https://github.com/linked-cm/cli/commit/2f0b4d349b98eea9271fad9028a2ddae824bcd29) Thanks [@flyon](https://github.com/flyon)! - Template's `@_linked/auth` dep range bumped from `~1.0` (which pinned to the broken 1.0.x empty-tarball releases) to `^1.1.0` (which has the actual `lib/`). Same for `@_linked/server-utils` (`^1.0.5` → `^1.0.6`) and `@_linked/schema` (`^1.0` → `^1.0.6` — both versions were empty before 1.0.6).
20
+
21
+ Also fixes `PersonPreview.tsx` template: `Person.update(...).for(source)` and `Person.delete(source)` now pass `{ id: source.id }` with an early-return guard, since `source.id` is optional on the shape type.
22
+
3
23
  ## 1.4.4
4
24
 
5
25
  ### Patch Changes
@@ -37,11 +37,12 @@
37
37
  ],
38
38
  "dependencies": {
39
39
  "@_linked/core": "^2.6",
40
- "@_linked/auth": "~1.0",
40
+ "@_linked/auth": "^1.1.0",
41
41
  "@_linked/server": "^2.0",
42
- "@_linked/server-utils": "^1.0.5",
43
- "@_linked/schema": "^1.0",
42
+ "@_linked/server-utils": "^1.0.6",
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) {
@@ -19,12 +19,13 @@ export const PersonPreview = linkedComponent(
19
19
  const [busy, setBusy] = useState(false);
20
20
 
21
21
  async function save() {
22
+ if (!source.id) return;
22
23
  setBusy(true);
23
24
  try {
24
25
  await Person.update({
25
26
  givenName: draftGiven,
26
27
  familyName: draftFamily,
27
- }).for(source);
28
+ }).for({ id: source.id });
28
29
  // Optimistic patch — no extra network round-trip needed.
29
30
  _refresh({ givenName: draftGiven, familyName: draftFamily });
30
31
  setEditing(false);
@@ -34,9 +35,10 @@ export const PersonPreview = linkedComponent(
34
35
  }
35
36
 
36
37
  async function remove() {
38
+ if (!source.id) return;
37
39
  setBusy(true);
38
40
  try {
39
- await Person.delete(source);
41
+ await Person.delete({ id: source.id });
40
42
  refreshList();
41
43
  } finally {
42
44
  setBusy(false);
@@ -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,187 @@
1
+ // Components showcase — demonstrates a slice of @_linked/primitives against
2
+ // the active @_linked/css theme. Open this page after signing in to see the
3
+ // design tokens in action. Replace with your own protected content.
4
+ import React, { useState } from 'react';
1
5
  import { DefaultLayout } from '../layout/DefaultLayout';
6
+ import { Button } from '@_linked/primitives/components/Button';
7
+ import { Input } from '@_linked/primitives/components/Input';
8
+ import { Switch } from '@_linked/primitives/components/Switch';
9
+ import { Checkbox } from '@_linked/primitives/components/Checkbox';
10
+ import { Slider } from '@_linked/primitives/components/Slider';
11
+ import { Progress } from '@_linked/primitives/components/Progress';
12
+ import { Avatar } from '@_linked/primitives/components/Avatar';
13
+ import { Tabs } from '@_linked/primitives/components/Tabs';
14
+ import { RadioGroup } from '@_linked/primitives/components/RadioGroup';
15
+ import { Label } from '@_linked/primitives/components/Label';
16
+ import { Separator } from '@_linked/primitives/components/Separator';
2
17
  import style from './Page1.module.css';
3
18
 
4
19
  export default function Page1() {
20
+ const [progress, setProgress] = useState(60);
21
+ const [sliderValue, setSliderValue] = useState([40]);
22
+ const [checked, setChecked] = useState(true);
23
+ const [switchOn, setSwitchOn] = useState(true);
24
+ const [radio, setRadio] = useState('comfy');
25
+ const [text, setText] = useState('');
26
+
5
27
  return (
6
28
  <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>
29
+ <div className={style.Page}>
30
+ <header className={style.Header}>
31
+ <h2>Components</h2>
32
+ <p>
33
+ A small tour of <code>@_linked/primitives</code> rendered against
34
+ the active <code>@_linked/css</code> theme. Tweak{' '}
35
+ <code>src/theme.css</code> tokens to re-skin every component on
36
+ this page.
37
+ </p>
38
+ </header>
39
+
40
+ <Tabs.Root defaultValue="forms" className={style.Tabs}>
41
+ <Tabs.List>
42
+ <Tabs.Trigger value="forms">Forms</Tabs.Trigger>
43
+ <Tabs.Trigger value="display">Display</Tabs.Trigger>
44
+ <Tabs.Trigger value="buttons">Buttons</Tabs.Trigger>
45
+ </Tabs.List>
46
+
47
+ <Tabs.Content value="forms" className={style.TabPanel}>
48
+ <section className={style.Card}>
49
+ <h3>Inputs</h3>
50
+ <div className={style.Field}>
51
+ <Label htmlFor="demo-name">Name</Label>
52
+ <Input
53
+ id="demo-name"
54
+ placeholder="Ada Lovelace"
55
+ value={text}
56
+ onChange={(e) => setText(e.target.value)}
57
+ />
58
+ </div>
59
+ <Separator />
60
+ <div className={style.Row}>
61
+ <Switch
62
+ checked={switchOn}
63
+ onCheckedChange={(v) => setSwitchOn(Boolean(v))}
64
+ />
65
+ <Label>Enable notifications</Label>
66
+ </div>
67
+ <div className={style.Row}>
68
+ <Checkbox
69
+ checked={checked}
70
+ onCheckedChange={(v) => setChecked(Boolean(v))}
71
+ />
72
+ <Label>I agree to the terms</Label>
73
+ </div>
74
+ </section>
75
+
76
+ <section className={style.Card}>
77
+ <h3>Density</h3>
78
+ <RadioGroup.Root
79
+ value={radio}
80
+ onValueChange={setRadio}
81
+ className={style.Stack}
82
+ >
83
+ <div className={style.Row}>
84
+ <RadioGroup.Item value="compact" id="r-compact" />
85
+ <Label htmlFor="r-compact">Compact</Label>
86
+ </div>
87
+ <div className={style.Row}>
88
+ <RadioGroup.Item value="comfy" id="r-comfy" />
89
+ <Label htmlFor="r-comfy">Comfortable</Label>
90
+ </div>
91
+ <div className={style.Row}>
92
+ <RadioGroup.Item value="spacious" id="r-spacious" />
93
+ <Label htmlFor="r-spacious">Spacious</Label>
94
+ </div>
95
+ </RadioGroup.Root>
96
+ </section>
97
+
98
+ <section className={style.Card}>
99
+ <h3>Slider</h3>
100
+ <Slider.Root
101
+ value={sliderValue}
102
+ onValueChange={setSliderValue}
103
+ min={0}
104
+ max={100}
105
+ step={1}
106
+ >
107
+ <Slider.Track>
108
+ <Slider.Range />
109
+ </Slider.Track>
110
+ <Slider.Thumb />
111
+ </Slider.Root>
112
+ <p className={style.Hint}>Value: {sliderValue[0]}</p>
113
+ </section>
114
+ </Tabs.Content>
115
+
116
+ <Tabs.Content value="display" className={style.TabPanel}>
117
+ <section className={style.Card}>
118
+ <h3>Avatar</h3>
119
+ <div className={style.AvatarRow}>
120
+ <Avatar.Root>
121
+ <Avatar.Fallback>AL</Avatar.Fallback>
122
+ </Avatar.Root>
123
+ <Avatar.Root>
124
+ <Avatar.Fallback>GH</Avatar.Fallback>
125
+ </Avatar.Root>
126
+ <Avatar.Root>
127
+ <Avatar.Fallback>RV</Avatar.Fallback>
128
+ </Avatar.Root>
129
+ </div>
130
+ </section>
131
+
132
+ <section className={style.Card}>
133
+ <h3>Progress</h3>
134
+ <Progress.Root value={progress} />
135
+ <div className={style.Row}>
136
+ <Button
137
+ size="small"
138
+ variant="outline"
139
+ onClick={() => setProgress((p) => Math.max(0, p - 10))}
140
+ >
141
+ −10
142
+ </Button>
143
+ <Button
144
+ size="small"
145
+ variant="outline"
146
+ onClick={() => setProgress((p) => Math.min(100, p + 10))}
147
+ >
148
+ +10
149
+ </Button>
150
+ <span className={style.Hint}>{progress}%</span>
151
+ </div>
152
+ </section>
153
+ </Tabs.Content>
154
+
155
+ <Tabs.Content value="buttons" className={style.TabPanel}>
156
+ <section className={style.Card}>
157
+ <h3>Variants</h3>
158
+ <div className={style.ButtonRow}>
159
+ <Button variant="solid">Solid</Button>
160
+ <Button variant="outline">Outline</Button>
161
+ <Button variant="ghost">Ghost</Button>
162
+ <Button variant="link">Link</Button>
163
+ </div>
164
+ </section>
165
+
166
+ <section className={style.Card}>
167
+ <h3>Colors</h3>
168
+ <div className={style.ButtonRow}>
169
+ <Button color="primary">Primary</Button>
170
+ <Button color="secondary">Secondary</Button>
171
+ <Button color="tertiary">Tertiary</Button>
172
+ </div>
173
+ </section>
174
+
175
+ <section className={style.Card}>
176
+ <h3>Sizes</h3>
177
+ <div className={style.ButtonRow}>
178
+ <Button size="small">Small</Button>
179
+ <Button size="medium">Medium</Button>
180
+ <Button size="large">Large</Button>
181
+ </div>
182
+ </section>
183
+ </Tabs.Content>
184
+ </Tabs.Root>
13
185
  </div>
14
186
  </DefaultLayout>
15
187
  );
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@_linked/cli",
3
- "version": "1.4.4",
3
+ "version": "1.5.0",
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.4",
3
+ "version": "1.5.0",
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.4",
3
+ "version": "1.5.0",
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",