@atmo-dev/kit 0.0.1 → 0.0.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/README.md CHANGED
@@ -1,215 +1,10 @@
1
1
  # Atmo Kit
2
2
 
3
- A Svelte 5 / Tailwind 4 UI kit for Florian’s Atmosphere apps, packaged as `@atmo-dev/kit` under the MIT license. Figtree, Sketchyicons, inherited base/accent palettes, vibrant primary actions, and inset-only depth. It is currently developed through local links; publishing is a separate release step.
4
-
5
- ## Develop
6
-
7
- ```sh
8
- pnpm install
9
- pnpm dev --host 127.0.0.1 --port 5190
10
- pnpm check
11
- pnpm test
12
- pnpm build
13
- ```
14
-
15
- - `/` — foundation and native controls
16
- - `/login` — interactive login examples, with local data and callbacks only
17
- - `/components` — popovers, segmented controls, editors, posts, and comments, with local data only
18
- - `/preview` — eight app mockups, separate from the library
19
-
20
- Mockups own their layouts and demo interactions, not a parallel set of control skins. Buttons, icon buttons, fields, avatars, inset images, surfaces, dialogs, and navigation use the actual library components. Shared component changes therefore appear in the mockups too; there is no separate preview compatibility stylesheet.
21
-
22
- `src/lib` is the library. `src/playground`, routes, and tests are not public exports. The design brief lives beside this repository, at `../DESIGN.md`.
23
-
24
- ## Theme and icons
25
-
26
- In a locally linked consumer with Tailwind 4, import the theme after Tailwind:
27
-
28
- ```css
29
- @import 'tailwindcss';
30
- @import '@atmo-dev/kit/theme.css';
31
- ```
32
-
33
- The theme includes an `@source './'` declaration for the packaged components. Your app must also scan its own Svelte source. Import this stylesheet once in the root layout. It includes the Figtree font.
34
-
35
- ```svelte
36
- <script lang="ts">
37
- import { Button, Icon } from '@atmo-dev/kit';
38
- import { Plus } from '@sketchyicons/svelte';
39
- </script>
40
-
41
- <div class="atmo zinc pink dark min-h-dvh">
42
- <Button><Icon img={Plus} />Create</Button>
43
- <Button class="red">Delete</Button>
44
- <section class="blue"><Button>Local blue accent</Button></section>
45
- </div>
46
- ```
47
-
48
- Use `.light` / `.dark`, one neutral base class, and one chromatic accent class. `baseColors` and `accentColors` list the supported ramps. All ramps include shades 50–950. Local hue classes update the inherited semantic colors without changing siblings. CSS variables configure typography, radii, duration, and inset depth.
49
-
50
- Primary buttons use `bg-accent-400 text-base-950 hover:bg-accent-300 active:bg-accent-400` directly in both modes—no primary-specific color tokens or mixed shades. Primary `IconButton`s inherit the same classes, and local hue classes still work. Secondary, ghost, and link treatments stay quiet. Semantic tokens remain for surfaces, text, borders, and focus where light/dark mode needs different shades.
51
-
52
- UI icons take explicit `img` data imports, not string names. Consumers importing icon data should declare `@sketchyicons/svelte` themselves. Caller classes are merged with Tailwind defaults; native control attributes, events, bindings, snippets, and refs remain available where appropriate. Modal and Tabs use Bits UI. Portaled content retains its source palette and font, including subsequent theme changes.
53
-
54
- `Surface` supports semantic containers (`div`, `section`, `article`, `aside`, `main`) and clickable cards with `as="button"`. Clickable surfaces are native buttons, default to `type="button"`, and retain keyboard activation, disabled behavior, and kit focus styles. Apps still own card content and layout.
55
-
56
- ## Navigation
57
-
58
- `IconRail` is bare icon navigation, not an application shell:
59
-
60
- ```svelte
61
- <script lang="ts">
62
- import { IconRail } from '@atmo-dev/kit';
63
- import { Home, Plus } from '@sketchyicons/svelte';
64
- </script>
65
-
66
- <IconRail
67
- label="App navigation"
68
- items={[
69
- { label: 'Home', icon: Home, href: '/', active: true },
70
- { label: 'Create', icon: Plus, onclick: create, primary: true }
71
- ]}
72
- />
73
- ```
74
-
75
- Items support real `href` links or click handlers, disabled states, current-page state, and unread badges. `backed` adds quiet individual backings. A `footer` snippet can contain an app-owned account button or menu. Tooltips use Bits UI. The default rail is 72px wide and becomes a bottom bar at 600px and below; apps own their content spacing.
76
-
77
- For a hamburger-opened mobile sidebar instead of a bottom bar, use `mobile="drawer"`. The same items become full-width icon-and-text rows; desktop keeps the compact rail:
78
-
79
- ```svelte
80
- <script lang="ts">
81
- import { Button, Icon, IconButton, IconRail } from '@atmo-dev/kit';
82
- import { Home, Menu, Plus, User } from '@sketchyicons/svelte';
83
- let open = $state(false);
84
- </script>
85
-
86
- <header>
87
- <IconButton
88
- label="Open navigation"
89
- aria-expanded={open}
90
- aria-controls="app-navigation"
91
- onclick={() => (open = true)}
92
- class="min-[601px]:hidden"><Icon img={Menu} /></IconButton
93
- >
94
- </header>
95
- <IconRail
96
- id="app-navigation"
97
- label="App navigation"
98
- mobile="drawer"
99
- bind:open
100
- items={[
101
- { label: 'Home', icon: Home, href: '/', active: true },
102
- { label: 'Create', icon: Plus, onclick: create, primary: true }
103
- ]}
104
- >
105
- {#snippet footer({ expanded, close })}
106
- <Button href="/account" variant="ghost" onclick={close}>
107
- <Icon img={User} />
108
- <span class={expanded ? '' : 'sr-only'}>Your account</span>
109
- </Button>
110
- {/snippet}
111
- </IconRail>
112
- <main class="min-[601px]:ml-18">…</main>
113
- ```
114
-
115
- The drawer uses its label as a screen-reader-only title, leaving only the close button above the links. It slides in over 130ms and skips the animation when reduced motion is preferred. It traps focus, locks background scrolling, closes on Escape/outside interaction or item selection, and restores focus to its opener. Resizing an open drawer to desktop closes it and focuses the visible rail. Navigation contents mount once. `footer({ expanded, close })` lets app-owned account controls show text in the drawer and close it before another action. Existing argument-free footer snippets still work. Apps place their own trigger and close `open` on programmatic route changes; no bottom padding is needed in drawer mode.
116
-
117
- `WorkspaceSidebar` is an inset desktop sidebar with a Bits-backed mobile drawer:
118
-
119
- ```svelte
120
- <script lang="ts">
121
- import { Button, WorkspaceSidebar } from '@atmo-dev/kit';
122
- let open = $state(false);
123
- </script>
124
-
125
- <Button class="min-[901px]:hidden" onclick={() => (open = true)}>Open navigation</Button>
126
- <WorkspaceSidebar label="Workspace navigation" bind:open>
127
- <strong class="block px-3 py-2">Studio</strong>
128
- <div class="mt-4 grid gap-1">
129
- <Button href="/notes" variant="ghost" class="justify-start">Notes</Button>
130
- <Button href="/settings" variant="ghost" class="justify-start">Settings</Button>
131
- </div>
132
- </WorkspaceSidebar>
133
- ```
134
-
135
- The drawer is used at 900px and below. Its contents mount once, avoiding duplicate IDs. Escape/outside interaction closes it and focus returns to the trigger; resizing back to desktop moves focus into the visible navigation. Close it after an app-specific navigation action with `open = false`.
136
-
137
- Both components accept caller classes and styles. Use `--atmo-nav-top` to clear a fixed app toolbar and `--atmo-sidebar-width` for desktop sidebar width. Navigation does not dictate a shared layout for every app.
138
-
139
- ## Event-app building blocks
140
-
141
- RSVP now consumes the kit locally. In its `apps/web` and `packages/ui` manifests the dependency is `"@atmo-dev/kit": "link:../../../00-atmo-kit/kit"`. Run `pnpm prepack` here before installing/running the consumer, or `pnpm exec svelte-package --watch` while editing components. The consumer deduplicates Svelte and allows this directory's font assets through Vite's development filesystem guard. No global links or publishing are involved.
142
-
143
- - `ToggleGroup` / `ToggleGroupItem`: Bits-backed single-choice segmented controls with keyboard navigation and checked/disabled semantics.
144
- - `Popover`: Bits-backed popover, with a `trigger({ props })` snippet for a real Button/IconButton and theme inheritance across its portal.
145
- - `InlineEditor`: a small TipTap plain-text editor with `bind:value`, `bind:editor`, accessible labels, single-line titles, plain-text paste, undo/redo, and optional `searchActors` mention autocomplete. The app owns the search adapter; the editor makes no requests without it.
146
- - `PostComposer`: inline editing plus a grapheme-aware character count. The app owns posting and must validate the final text/byte limit before writing a record. `editorJsonToBlueskyPost(editor.getJSON())` retains selected mention DIDs and generates UTF-8 facets for mentions, links, and hashtags. Manually typed handles remain app-resolved.
147
- - `LinkCard`, `PostContent`, and `NestedComments`: data-driven post presentation, escaped rich text, nested replies, images, link previews, quotes, and lazily loaded HLS video. `blueskyPostToPostData` normalizes public AppView post views without fetching them or accessing a session. Reply/like links open Bluesky; authenticated mutations remain app-owned.
148
- - `launchConfetti`: explicitly invoked and lazily loaded; respects reduced motion.
149
-
150
- Additional Tailwind neutral ramps (`mist`, `mauve`, `olive`, `taupe`) preserve saved event themes. The app default remains zinc + pink; `sand` and `sage` are aliases for saved legacy names. Portaled dialogs and popovers follow subsequent ancestor palette changes. Non-dismissible Modal states also disable the close button.
151
-
152
- Event-specific cards, calendars, scheduling, record writes and auth stay in RSVP. This is not a compatibility layer for the previous UI library.
153
-
154
- ## Component examples
155
-
156
- Open `/components` for interactive, local-only examples:
157
-
158
- - Edit a link card in a Popover, or open a Popover inside a Modal. Escape closes the innermost layer and restores its trigger.
159
- - Edit a single-line title with undo/redo, external reset, and disabled state.
160
- - Compose text with local mention suggestions; inspect serialized UTF-8 facets and preview without publishing. Empty/over-limit submit rules belong to the example app, not the editor.
161
- - Switch post attachments with ToggleGroup. Arrow keys move focus, Space selects, and disabled choices are skipped.
162
- - Explore linked text, photos, link cards, unavailable quotes, native video controls, and nested comments.
163
-
164
- All media and actor suggestions in this page are local. The [silent HLS fixture](static/playground/video/README.md) exercises actual playback, source changes, and cleanup without an external stream. Real media still needs suitable captions or an accessible source/transcript.
165
-
166
- Tests cover these states in light/dark mode, scoped portals, nested focus restoration, empty and stale mention results, keyboard interaction, 320–1920px layouts, reduced motion, inset-only depth, and automated WCAG A/AA checks. Automated scans do not replace manual assistive-technology testing.
167
-
168
- ## Login
169
-
170
- `LoginForm` and `LoginDialog` rebuild the existing Atmo UI login flow with this kit’s controls and Sketchyicons. They support handle validation, optional actor typeahead, selected accounts, recent profiles, permission review, signup confirmation, busy states, errors, and retry.
171
-
172
- ```svelte
173
- <script lang="ts">
174
- import { LoginDialog, createActorSearch, type LoginCallback } from '@atmo-dev/kit';
175
- let open = $state(false);
176
-
177
- // Explicit opt-in to public AppView search. Alternatively inject your own provider,
178
- // or omit searchActors for a plain handle field with no search requests.
179
- const searchActors = createActorSearch();
180
- const login: LoginCallback = async (handle, actor, options) => {
181
- await appLogin(handle, actor, options); // Your existing OAuth/session integration.
182
- };
183
- </script>
184
-
185
- <LoginDialog bind:open {login} {searchActors} signup={() => appSignup()} />
186
- ```
187
-
188
- `LoginForm` takes the same login options without `open` / `closeOnSuccess`. It can be placed directly on a page; no enclosing Surface is required. Form attributes and `ref` refer to the form. `LoginDialog` uses `class` for its modal and `formClass` for the inner form.
189
-
190
- ### Callback contract
191
-
192
- - `login(handle, actor?, options?)` receives a normalized, syntactically valid handle. An actor is supplied only when the user selected one; a typed handle never produces invented DID/profile data.
193
- - A thrown error is displayed. Returning `false` leaves the flow open without calling `onSuccess`. Returning `true` or `undefined` accepts the callback result; the dialog closes by default. Set `closeOnSuccess={false}` to keep it open.
194
- - `onSuccess` means **the callback completed**, not that an OAuth redirect finished or a session was verified. Only your app’s verified session state should determine whether a user is authenticated.
195
- - `signup` is called only after the separate confirmation step. Signup and OAuth redirects, cancellation, networking, sessions, granted-scope verification, and business rules remain app-owned.
196
- - Closing/unmounting a pending form ignores its later UI completion. This cannot undo an app callback that has already started a request or redirect.
197
- - `loginOnSelect` defaults to true. Set it to false to select a suggestion, then submit explicitly. Recent-account selections always start the login flow, with permission review first when configured.
198
- - `initialHandle` initializes the field. `onStepChange` reports `login`, `permissions`, or `signup`.
199
- - Customize `title`, `description`, `showApps`, and the `footer(step)` snippet. An optional `children` snippet sits before the handle-submit button. `ActorSearchField` and `RecentAccounts` are also available independently.
200
-
201
- ### Search and recent profiles
202
-
203
- Search is debounced, abortable, race-safe, and optional. Results do not validate ownership and failed search never blocks submitting a full handle. The included `createActorSearch({ host, limit, fetch })` helper performs no work until called. Configure hosts in trusted app code, not from untrusted user input.
204
-
205
- `bind:recentAccounts` lets an app own its history. Persistence is **off by default**. Set `persistRecentAccounts` to use origin-local storage, optionally with `recentAccountOptions={{ storage, key, max }}`. Storage failures are non-fatal; only profile display fields and a last-used timestamp are retained, never credentials or tokens. Forgetting a recent profile does not log out an account.
206
-
207
- For explicit persistence outside the component, use `loadRecentAccounts`, `writeRecentAccounts`, `saveRecentAccount`, and `removeRecentAccount`. To import old Fox UI history without overwriting its format, read `loadRecentAccounts({ key: 'recent-logins' })` once and save those profiles under the new default key. No automatic migration occurs.
208
-
209
- ### Permission review
210
-
211
- Pass `permissions` to add a review step before invoking `login`. A permission has a unique `id`, `label`, `description`, `scopes`, optional Sketchyicons `icon`, `required`, and `defaultSelected`. Required items cannot be deselected. Optional items default to selected, matching the previous component; explicitly set `defaultSelected: false` when they should start off.
212
-
213
- The callback receives `{ permissionIds, scopes }`; scopes are deduplicated with `baseScopes` (default `['atproto']`). These are requested permissions, **not a consent receipt or proof of granted OAuth access**. Your OAuth adapter must apply the requested scopes and verify what was granted. Without a review step, the third argument is omitted and the app retains its existing scope policy.
214
-
215
- The service-logo strip is static and decorative. These are existing brand marks, separate from the handdrawn UI icons; see `src/lib/components/login/brands/README.md`. Login lives with the other components in `src/lib/components/login/` and shares the package's root MIT `LICENSE`.
3
+ Svelte 5 and Tailwind CSS 4 components for Atmo apps.
4
+
5
+ - Install: `pnpm add @atmo-dev/kit`.
6
+ - Styles: import `@atmo-dev/kit/theme.css` after `tailwindcss`; wrap your app in `class="atmo zinc pink light"` (or `dark`).
7
+ - Develop: `pnpm install && pnpm dev`. Components at `/components`, app mockups at `/preview`.
8
+ - Validate: `pnpm lint && pnpm check && pnpm test:ci && pnpm build`.
9
+ - Releases: `pnpm changeset`, then merge the generated release PR. [Details](.changeset/README.md).
10
+ - License: [MIT](LICENSE).
@@ -38,7 +38,7 @@
38
38
  footer?: Snippet<[{ expanded: boolean; close: () => void }]>;
39
39
  ref?: HTMLElement | null;
40
40
  } = $props();
41
- const small = new MediaQuery('(max-width: 600px)', false);
41
+ const small = new MediaQuery('(width < 40rem)', false);
42
42
  const close = () => (open = false);
43
43
  let drawerWasOpen = false;
44
44
  $effect(() => {
@@ -112,13 +112,13 @@
112
112
  data-slot="icon-rail"
113
113
  data-backed={backed}
114
114
  class={cn(
115
- 'fixed top-[var(--atmo-nav-top,0px)] bottom-0 left-0 z-40 flex w-18 flex-col items-center bg-transparent pt-6 pb-5 [@media(max-width:600px)]:top-auto [@media(max-width:600px)]:right-0 [@media(max-width:600px)]:h-[calc(62px+env(safe-area-inset-bottom))] [@media(max-width:600px)]:w-full [@media(max-width:600px)]:flex-row [@media(max-width:600px)]:justify-around [@media(max-width:600px)]:bg-page [@media(max-width:600px)]:px-2 [@media(max-width:600px)]:pt-1.5 [@media(max-width:600px)]:pb-[calc(6px+env(safe-area-inset-bottom))]',
116
- mobile === 'drawer' && '[@media(max-width:600px)]:hidden',
115
+ 'fixed top-[var(--atmo-nav-top,0px)] bottom-0 left-0 z-40 flex w-18 flex-col items-center bg-transparent pt-6 pb-5 max-sm:top-auto max-sm:right-0 max-sm:h-[calc(62px+env(safe-area-inset-bottom))] max-sm:w-full max-sm:flex-row max-sm:justify-around max-sm:bg-page max-sm:px-2 max-sm:pt-1.5 max-sm:pb-[calc(6px+env(safe-area-inset-bottom))]',
116
+ mobile === 'drawer' && 'max-sm:hidden',
117
117
  className
118
118
  )}
119
119
  >
120
120
  <div
121
- class="flex flex-col items-center gap-3 [@media(max-width:600px)]:min-w-0 [@media(max-width:600px)]:flex-1 [@media(max-width:600px)]:flex-row [@media(max-width:600px)]:justify-around [@media(max-width:600px)]:gap-0"
121
+ class="flex flex-col items-center gap-3 max-sm:min-w-0 max-sm:flex-1 max-sm:flex-row max-sm:justify-around max-sm:gap-0"
122
122
  >
123
123
  {#each items as item (item.label)}
124
124
  <Tooltip.Root disabled={item.disabled ?? false}
@@ -134,9 +134,8 @@
134
134
  aria-current={item.active ? 'page' : undefined}
135
135
  data-part="item"
136
136
  class={cn(
137
- 'relative size-11 rounded-(--atmo-radius-button) text-muted hover:bg-recess/55 aria-[current=page]:text-action [@media(max-width:600px)]:size-10',
138
- item.primary &&
139
- 'mt-2 text-action hover:text-action [@media(max-width:600px)]:mt-0',
137
+ 'relative size-11 rounded-(--atmo-radius-button) text-muted hover:bg-recess/55 aria-[current=page]:text-action max-sm:size-10',
138
+ item.primary && 'mt-2 text-action hover:text-action max-sm:mt-0',
140
139
  backed && 'bg-recess/45 hover:bg-recess/75'
141
140
  )}
142
141
  >
@@ -157,9 +156,7 @@
157
156
  >
158
157
  {/each}
159
158
  </div>
160
- {#if footer}<div
161
- class="mt-auto [@media(max-width:600px)]:mt-0 [@media(max-width:600px)]:ml-1"
162
- >
159
+ {#if footer}<div class="mt-auto max-sm:mt-0 max-sm:ml-1">
163
160
  {@render footer({ expanded: false, close })}
164
161
  </div>{/if}
165
162
  </nav>
@@ -0,0 +1,22 @@
1
+ <script lang="ts">
2
+ let {
3
+ title,
4
+ siteName,
5
+ separator = ' — '
6
+ }: {
7
+ title?: string | null;
8
+ siteName: string;
9
+ separator?: string;
10
+ } = $props();
11
+
12
+ let normalizedTitle = $derived(title?.trim());
13
+ let pageTitle = $derived(
14
+ !normalizedTitle || normalizedTitle === siteName
15
+ ? siteName
16
+ : `${normalizedTitle}${separator}${siteName}`
17
+ );
18
+ </script>
19
+
20
+ <svelte:head>
21
+ <title>{pageTitle}</title>
22
+ </svelte:head>
@@ -0,0 +1,8 @@
1
+ type $$ComponentProps = {
2
+ title?: string | null;
3
+ siteName: string;
4
+ separator?: string;
5
+ };
6
+ declare const PageTitle: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type PageTitle = ReturnType<typeof PageTitle>;
8
+ export default PageTitle;
@@ -22,7 +22,7 @@
22
22
  Object.fromEntries(Object.entries(rest).filter(([, value]) => value !== null))
23
23
  );
24
24
  let desktop = $state<HTMLElement | null>(null);
25
- const mobile = new MediaQuery('(max-width: 900px)', false);
25
+ const mobile = new MediaQuery('(width < 48rem)', false);
26
26
  let drawerWasOpen = false;
27
27
  $effect(() => {
28
28
  const leavingDrawer = !mobile.current && drawerWasOpen;
@@ -50,7 +50,7 @@
50
50
  aria-label={label}
51
51
  data-slot="workspace-sidebar"
52
52
  class={cn(
53
- 'fixed top-[calc(var(--atmo-nav-top,0px)+12px)] bottom-3 left-3 z-40 w-[var(--atmo-sidebar-width,238px)] overflow-hidden rounded-[21px_18px_23px_19px] p-0 [@media(max-width:900px)]:hidden',
53
+ 'fixed top-[calc(var(--atmo-nav-top,0px)+12px)] bottom-3 left-3 z-40 w-[var(--atmo-sidebar-width,238px)] overflow-hidden rounded-[21px_18px_23px_19px] p-0 max-md:hidden',
54
54
  className
55
55
  )}
56
56
  >
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export { default as Textarea } from './components/Textarea.svelte';
7
7
  export { default as Select } from './components/Select.svelte';
8
8
  export { default as Checkbox } from './components/Checkbox.svelte';
9
9
  export { default as Label } from './components/Label.svelte';
10
+ export { default as PageTitle } from './components/PageTitle.svelte';
10
11
  export { default as Heading } from './components/Heading.svelte';
11
12
  export { default as Subheading } from './components/Subheading.svelte';
12
13
  export { default as Surface } from './components/Surface.svelte';
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export { default as Textarea } from './components/Textarea.svelte';
5
5
  export { default as Select } from './components/Select.svelte';
6
6
  export { default as Checkbox } from './components/Checkbox.svelte';
7
7
  export { default as Label } from './components/Label.svelte';
8
+ export { default as PageTitle } from './components/PageTitle.svelte';
8
9
  export { default as Heading } from './components/Heading.svelte';
9
10
  export { default as Subheading } from './components/Subheading.svelte';
10
11
  export { default as Surface } from './components/Surface.svelte';
package/dist/theme.css CHANGED
@@ -36,8 +36,6 @@
36
36
  --color-control-hover: var(--ui-control-hover);
37
37
  --color-field: var(--ui-field);
38
38
  --color-action: var(--ui-action);
39
- --color-on-action: var(--ui-on-action);
40
- --color-action-hover: var(--ui-action-hover);
41
39
  --color-accent-soft: var(--ui-accent-soft);
42
40
  --color-focus: var(--ui-focus);
43
41
  --font-sans: var(--atmo-font-sans);
@@ -138,8 +136,6 @@
138
136
  --ui-control-line: light-dark(var(--base-300), var(--base-800));
139
137
  --ui-control-hover: light-dark(var(--base-400), var(--base-700));
140
138
  --ui-action: light-dark(var(--accent-700), var(--accent-300));
141
- --ui-on-action: light-dark(var(--accent-50), var(--accent-950));
142
- --ui-action-hover: light-dark(var(--accent-800), var(--accent-200));
143
139
  --ui-accent-soft: light-dark(
144
140
  var(--accent-50),
145
141
  color-mix(in srgb, var(--accent-950) 65%, var(--base-950))
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@atmo-dev/kit",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "The shared UI foundation for Atmo apps.",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/flo-bit/atmo-kit.git"
9
+ },
6
10
  "publishConfig": {
7
11
  "access": "public"
8
12
  },
@@ -31,6 +35,7 @@
31
35
  },
32
36
  "devDependencies": {
33
37
  "@axe-core/playwright": "^4.14.0",
38
+ "@changesets/cli": "^2.31.1",
34
39
  "@eslint/js": "^10.0.1",
35
40
  "@playwright/test": "^1.60.0",
36
41
  "@sveltejs/adapter-auto": "^8.0.0",
@@ -97,6 +102,10 @@
97
102
  "format": "prettier --write .",
98
103
  "test:unit": "vitest",
99
104
  "test": "pnpm test:unit --run && pnpm test:e2e",
100
- "test:e2e": "playwright test"
105
+ "test:ci": "pnpm test:unit --run --no-file-parallelism && pnpm test:e2e",
106
+ "test:e2e": "playwright test",
107
+ "changeset": "changeset",
108
+ "version-packages": "changeset version && pnpm install --lockfile-only --no-frozen-lockfile --ignore-scripts",
109
+ "release": "pnpm prepack && changeset publish"
101
110
  }
102
111
  }