@stealthscale/component-feedback 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Stealth Scale B.V.
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,101 @@
1
+ # @stealthscale/component-feedback
2
+
3
+ Draws the system reporting on itself: what is loading, what went wrong, what state a thing is in.
4
+ Every component binds a recipe and draws nothing of its own, so a theme restyles all of them by
5
+ extending the recipe. The preset under `./theme` registers the recipes with an application's
6
+ compiler.
7
+
8
+ Every value a theme can change on a component is an axis of its recipe, so a caller sets it as a
9
+ prop and writes no style. A caller changes the element a component draws with `as`.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ pnpm add @stealthscale/component-feedback
15
+ ```
16
+
17
+ The package peers on `react` and `@stealthscale/theme`. An application lists the preset under
18
+ `./theme` among the presets its compiler installs.
19
+
20
+ ## Skeleton
21
+
22
+ Stands in for content that has not arrived. It wraps that content rather than replacing it, so a
23
+ caller writes one tree and sets one prop, and the stand-in comes out the size of the thing it stands
24
+ in for without anybody stating a width. While it waits it hides everything inside it. Once the
25
+ content arrives the stand-in fades out and the content is shown.
26
+
27
+ ```tsx
28
+ import { Skeleton } from "@stealthscale/component-feedback";
29
+
30
+ <Skeleton loading={pending}>
31
+ <Avatar src={person.photo} />
32
+ </Skeleton>;
33
+ <Skeleton motion="shimmer" radius="full" />;
34
+ ```
35
+
36
+ | Axis | Values | Default |
37
+ | --------- | -------------------------- | ------- |
38
+ | `loading` | `true`, `false` | `true` |
39
+ | `motion` | `none`, `pulse`, `shimmer` | `pulse` |
40
+ | `radius` | `l1`, `l2`, `l3`, `full` | `l2` |
41
+
42
+ The element carries no role. A reader learns more from being told the region is busy than from being
43
+ told each box is, so a page states `aria-busy` on whatever is waiting and each bar announces nothing
44
+ of its own.
45
+
46
+ ## SkeletonText
47
+
48
+ Stands in for a paragraph of text. Every length is read off the line it stands in for, so a bar is
49
+ one line tall and the space between two is half a line. Place it where text is read and it comes out
50
+ the size of that text, so the page does not jump when the real words replace it.
51
+
52
+ ```tsx
53
+ import { SkeletonText } from "@stealthscale/component-feedback";
54
+
55
+ <SkeletonText />;
56
+ <SkeletonText lines={5} motion="shimmer" />;
57
+ ```
58
+
59
+ The last bar of several is short, because a paragraph rarely fills its final line and a block of
60
+ bars all one width reads as a table rather than as writing. `lines` defaults to three and never
61
+ draws fewer than one. Draw this while the text is loading and draw the text itself once it arrives,
62
+ so nothing here takes a loading state.
63
+
64
+ ## EmptyState
65
+
66
+ Draws the panel a page shows where there is nothing to show, composed as `EmptyState.Root` holding a
67
+ mark, a heading and a line saying what would be here.
68
+
69
+ ```tsx
70
+ import { EmptyState } from "@stealthscale/component-feedback";
71
+
72
+ <EmptyState.Root size="lg">
73
+ <EmptyState.Content>
74
+ <EmptyState.Indicator aria-hidden>
75
+ <InboxIcon />
76
+ </EmptyState.Indicator>
77
+ <EmptyState.Title>No invoices yet</EmptyState.Title>
78
+ <EmptyState.Description>Send your first one to get started.</EmptyState.Description>
79
+ </EmptyState.Content>
80
+ </EmptyState.Root>;
81
+ ```
82
+
83
+ | Axis | Values | Default |
84
+ | ------ | ------------------------------------------------- | ------- |
85
+ | `size` | `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl` | `md` |
86
+
87
+ One axis sets four parts together. The room inside the panel, the gap in the content, the box of the
88
+ mark and the size of the title each read the scale of that name, so a small panel in a sidebar and a
89
+ large one filling a page are one name apart. The description holds its size, because a line of
90
+ explanation is read at the size the rest of the page is read at however big the panel is.
91
+
92
+ The mark fills whatever box its size states, so a caller passes a glyph without sizing it. Hide it
93
+ with `aria-hidden`, since the title beneath says the same thing in words. The title is an `h2`,
94
+ which suits a panel standing in for a section's content. A page whose outline puts it deeper states
95
+ its own level with `as`.
96
+
97
+ The root carries no role. A page of empty panels would otherwise be a page of landmarks.
98
+
99
+ ## Licence
100
+
101
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1 @@
1
+ {"$schema":"http://cyclonedx.org/schema/bom-1.7.schema.json","bomFormat":"CycloneDX","specVersion":"1.7","version":1,"metadata":{"lifecycles":[{"phase":"build"}],"tools":{"components":[{"type":"application","name":"rolldown","version":"1.2.7"},{"type":"application","name":"vite","version":"8.2.2"},{"type":"library","name":"core","group":"@arethetypeswrong","version":"0.18.5","bom-ref":"pkg:npm/%40arethetypeswrong/core@0.18.5","author":"Andrew Branch","description":"The API behind arethetypeswrong.github.io","hashes":[{"alg":"SHA-512","content":"f72b63cc6c318e6f54cfb23d6af7dbb79be542deae93db914444b3263aabce797a58abc8e9dc184e8faf277534d96aeafe64778aa97f3f386f1e129d2480230d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40arethetypeswrong/core@0.18.5","externalReferences":[{"url":"https://github.com/arethetypeswrong/arethetypeswrong.github.io.git#packages/core","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20"}]},{"type":"library","name":"theme","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/theme@0.3.0","description":"Publishes the foundation every recipe is written against, the runtime every component binds its recipe with, and the vocabulary a theme is written in.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/theme@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#foundations/theme","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/foundations/theme#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-react","group":"@stealthscale","version":"0.8.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-react@0.8.0","description":"Adds the JSX transform, the React lint rules, a test document and an MDX compiler to a package that renders.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-react@0.8.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config-react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config-react#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-theme","group":"@stealthscale","version":"0.1.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-theme@0.1.0","description":"Adds the runtime generator to a design-system package and the stylesheet compiler to an application.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-theme@0.1.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config-theme","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config-theme#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config-typescript","group":"@stealthscale","version":"0.3.0","bom-ref":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","description":"Sets the TypeScript options every stealthscale package compiles with.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config-typescript@0.3.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config-typescript","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config-typescript#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"vite-config","group":"@stealthscale","version":"0.6.0","bom-ref":"pkg:npm/%40stealthscale/vite-config@0.6.0","description":"Configures a package from five Vite+ tiers and a named layer for every block.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/vite-config@0.6.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#packages/vite-config","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/packages/vite-config#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}]},{"type":"library","name":"react","group":"@testing-library","version":"16.3.3","bom-ref":"pkg:npm/%40testing-library/react@16.3.3","author":"Kent C. Dodds <me@kentcdodds.com> (https://kentcdodds.com)","description":"Simple and complete React DOM testing utilities that encourage good testing practices.","hashes":[{"alg":"SHA-512","content":"528d7ddcd8106cf333ea5aeb86d45040570c0ba45efc42cb15b6ee54bdf4583959c65a597fdfe53074c05713d12f0d6ad62bbd389991d5cd812e210d46cb5d06"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40testing-library/react@16.3.3","externalReferences":[{"url":"https://github.com/testing-library/react-testing-library/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/testing-library/react-testing-library","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://github.com/testing-library/react-testing-library#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=18"}]},{"type":"library","name":"react-dom","group":"@types","version":"19.3.0","bom-ref":"pkg:npm/%40types/react-dom@19.3.0","description":"TypeScript definitions for react-dom","hashes":[{"alg":"SHA-512","content":"648edb538da66575ca1e7fea34b130d88adb888354ed7e7ebdf81d8b10479023696165e32a07d0fcffaec866f90a338b07d51c9d37a0debca542d5768729b8e1"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/react-dom@19.3.0","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/react-dom","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-dom","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"react","group":"@types","version":"19.3.0","bom-ref":"pkg:npm/%40types/react@19.3.0","description":"TypeScript definitions for react","hashes":[{"alg":"SHA-512","content":"374ac50ae1fd628c46f7f9bad65f4c7e924a7e62ce554d1e9bb8a9233e9346049292f45e2c1f6f2fce4607ecabf01b3995eaa9be0f7a252c05e194b5b38be242"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40types/react@19.3.0","externalReferences":[{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped.git#types/react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"babel-plugin-react-compiler","version":"1.0.0","bom-ref":"pkg:npm/babel-plugin-react-compiler@1.0.0","description":"Babel plugin for React Compiler.","hashes":[{"alg":"SHA-512","content":"2319bcb457e828a20f61d0822984ecaaff85778209d0342a3321229a8fa9c5438c511f5c54f9704eb16df40beefb771be99a77980ce5fadd4cac6d9fc712acc7"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/babel-plugin-react-compiler@1.0.0","externalReferences":[{"url":"git+https://github.com/facebook/react.git#compiler/packages/babel-plugin-react-compiler","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""}]},{"type":"library","name":"happy-dom","version":"20.14.5","bom-ref":"pkg:npm/happy-dom@20.14.5","author":"David Ortner","description":"Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG DOM and HTML.","hashes":[{"alg":"SHA-512","content":"c7f47392958ee346d38c8a13df4890b6deb814b2e61ff89171408dd97fff6cbc7b1f789f91d7cf5f2aacae8fce62dab32008622cc300ee69a2391f42dcd38a8d"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/happy-dom@20.14.5","externalReferences":[{"url":"https://github.com/capricorn86/happy-dom","type":"vcs","comment":"as detected from PackageJson property \"repository\""},{"url":"https://github.com/capricorn86/happy-dom","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=20.0.0"}]},{"type":"library","name":"oxc-transform-react","version":"0.149.0","bom-ref":"pkg:npm/oxc-transform-react@0.149.0","author":"Boshen and oxc contributors","description":"Oxc React Compiler Node API","hashes":[{"alg":"SHA-512","content":"69bdddc5c3ed90349f211f6d35dc4752d9a974bd258479ddb010fd214014e41c6d26dc061bff39367473b367f62b0a2e3641e5edc692b3030b41e52fc3714447"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/oxc-transform-react@0.149.0","externalReferences":[{"url":"https://github.com/oxc-project/oxc/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/oxc-project/oxc.git#napi/transform-react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://oxc.rs","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^20.19.0 || >=22.12.0"}]},{"type":"library","name":"react-dom","version":"19.3.0","bom-ref":"pkg:npm/react-dom@19.3.0","description":"React package for working with the DOM.","hashes":[{"alg":"SHA-512","content":"24393c76089fe753a31680c4ef4f8e4fd202c98afeebd1e59a284dc29d7e36c7db9dadede6c22209af59264b43990e3fd5bfeb9f6ea1200476b985c332be6bd1"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/react-dom@19.3.0","externalReferences":[{"url":"https://github.com/react/react/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/react/react.git#packages/react-dom","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://react.dev/","type":"website","comment":"as detected from PackageJson property \"homepage\""}]},{"type":"library","name":"react","version":"19.3.0","bom-ref":"pkg:npm/react@19.3.0","description":"React is a JavaScript library for building user interfaces.","hashes":[{"alg":"SHA-512","content":"13c2d471bb415addb46db9766281dfc7864305dc554df38ab42667f5c0d227897afe7ba8029729201723e3bb76c19a155fc836647b8c1db892860091d53e52a2"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/react@19.3.0","externalReferences":[{"url":"https://github.com/react/react/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"https://github.com/react/react.git#packages/react","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://react.dev/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=0.10.0"}]},{"type":"library","name":"typescript","version":"7.0.2","bom-ref":"pkg:npm/typescript@7.0.2","author":"Microsoft Corp.","description":"TypeScript is a language for application scale JavaScript development","hashes":[{"alg":"SHA-512","content":"f0561abbdea8dcd28e85b8ca8bfa8dbc6fd6e63873c646dd9b9b23f406d9ff94f9b16aa7de12602df1b1dbbb11299593bf2cc23fc74b4414dfe6d05349155434"}],"licenses":[{"license":{"id":"Apache-2.0"}}],"purl":"pkg:npm/typescript@7.0.2","externalReferences":[{"url":"https://github.com/microsoft/TypeScript/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"https://github.com/microsoft/TypeScript.git","type":"vcs","comment":"as detected from PackageJson property \"repository.url\""},{"url":"https://www.typescriptlang.org/","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=16.20.0"}]},{"type":"library","name":"vitest","version":"4.1.11","bom-ref":"pkg:npm/vitest@4.1.11","author":"Anthony Fu <anthonyfu117@hotmail.com>","description":"Next generation testing framework powered by Vite","hashes":[{"alg":"SHA-512","content":"7e1002acd5d489d21b19206be4595bb8190eed5582d59c8b9740cee025360eb42800fc57f3862cc6cf877864298a2e656565754388016534eee3d985f80e8477"}],"licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/vitest@4.1.11","externalReferences":[{"url":"https://github.com/vitest-dev/vitest/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs.url\""},{"url":"git+https://github.com/vitest-dev/vitest.git#packages/vitest","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://vitest.dev","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":"^20.0.0 || ^22.0.0 || >=24.0.0"}]}]},"component":{"type":"library","name":"component-feedback","group":"@stealthscale","version":"0.1.0","bom-ref":"pkg:npm/%40stealthscale/component-feedback@0.1.0","description":"Draws the system reporting on itself: what is loading, what went wrong, what state a thing is in.","licenses":[{"license":{"id":"MIT"}}],"purl":"pkg:npm/%40stealthscale/component-feedback@0.1.0","externalReferences":[{"url":"https://github.com/stealth-scale/config/issues","type":"issue-tracker","comment":"as detected from PackageJson property \"bugs\""},{"url":"git+https://github.com/stealth-scale/config.git#components/feedback","type":"vcs","comment":"as detected from PackageJson property \"repository.url\" and \"repository.directory\""},{"url":"https://github.com/stealth-scale/config/tree/main/components/feedback#readme","type":"website","comment":"as detected from PackageJson property \"homepage\""}],"properties":[{"name":"cdx:npm:package:constraint:engine:node","value":">=26.0.0"}],"evidence":{"licenses":[{"license":{"name":"file: LICENSE","text":{"content":"TUlUIExpY2Vuc2UKCkNvcHlyaWdodCAoYykgMjAyNiBTdGVhbHRoIFNjYWxlIEIuVi4KClBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkKb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJlIiksIHRvIGRlYWwKaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cwp0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsCmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcwpmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgoKVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsCmNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuCgpUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUgpJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFCkFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUKU09GVFdBUkUuCg==","contentType":"text/plain","encoding":"base64"}}}]}},"supplier":{"name":"Stealth Scale B.V.","url":["https://stealthscale.io"]}},"components":[],"dependencies":[{"ref":"pkg:npm/%40stealthscale/component-feedback@0.1.0"}]}
@@ -0,0 +1,142 @@
1
+ import { ComponentProps, ReactElement } from "react";
2
+ //#region src/empty-state/content.d.ts
3
+ /**
4
+ * Centres what it holds, in a column, at the gap its size states.
5
+ */
6
+ declare const Content: import("@stealthscale/theme").StyledComponent<"div", {}>;
7
+ /**
8
+ * Describes what the content takes.
9
+ */
10
+ type ContentProps = ComponentProps<typeof Content>;
11
+ //#endregion
12
+ //#region src/empty-state/description.d.ts
13
+ /**
14
+ * Draws the explanation, quieter than the title and at one size whatever the panel's is.
15
+ */
16
+ declare const Description: import("@stealthscale/theme").StyledComponent<"p", {}>;
17
+ /**
18
+ * Describes what the description takes.
19
+ */
20
+ type DescriptionProps = ComponentProps<typeof Description>;
21
+ //#endregion
22
+ //#region src/empty-state/indicator.d.ts
23
+ /**
24
+ * Draws the mark at the box its size states.
25
+ */
26
+ declare const Indicator: import("@stealthscale/theme").StyledComponent<"div", {}>;
27
+ /**
28
+ * Describes what the indicator takes.
29
+ */
30
+ type IndicatorProps = ComponentProps<typeof Indicator>;
31
+ //#endregion
32
+ //#region src/empty-state/root.d.ts
33
+ /**
34
+ * Draws the panel and sets the size every part below it reads.
35
+ */
36
+ declare const Root: import("@stealthscale/theme").StyledComponent<"div", {
37
+ readonly size?: "2xl" | "3xl" | "4xl" | "lg" | "md" | "sm" | "xl" | "xs";
38
+ }>;
39
+ /**
40
+ * Describes what the panel takes.
41
+ */
42
+ type RootProps = ComponentProps<typeof Root>;
43
+ //#endregion
44
+ //#region src/empty-state/title.d.ts
45
+ /**
46
+ * Draws the title at the size the panel states.
47
+ */
48
+ declare const Title: import("@stealthscale/theme").StyledComponent<"h2", {}>;
49
+ /**
50
+ * Describes what the title takes.
51
+ */
52
+ type TitleProps = ComponentProps<typeof Title>;
53
+ declare namespace index_d_exports {
54
+ export { Content, ContentProps, Description, DescriptionProps, Indicator, IndicatorProps, Root, RootProps, Title, TitleProps };
55
+ }
56
+ //#endregion
57
+ //#region src/skeleton-text/context.d.ts
58
+ /**
59
+ * Binds the skeleton paragraph's recipe to the element that draws it.
60
+ *
61
+ * @remarks
62
+ * Apart from the recipe, because an application's compiler reads the recipe at build time and
63
+ * the binding needs the runtime.
64
+ */
65
+ /**
66
+ * Binds the recipe once, for the column the bars are drawn in.
67
+ */
68
+ declare const PropsProvider$1: import("react").Provider<import("@stealthscale/theme").DataAttrs & Partial<{}>>, withContext$1: <Tag extends import("react").ElementType>(Component: Tag, options?: import("@stealthscale/theme").JsxFactoryOptions<import("@stealthscale/theme").ComponentProps<Tag> & Partial<{}>> | undefined) => import("@stealthscale/theme").StyledComponent<Tag, {}>;
69
+ //#endregion
70
+ //#region src/skeleton/skeleton.d.ts
71
+ /**
72
+ * Stands in for content that has not arrived, taking the box of whatever it wraps.
73
+ */
74
+ export declare const Skeleton: import("@stealthscale/theme").StyledComponent<"div", {
75
+ readonly loading?: boolean;
76
+ readonly motion?: "none" | "pulse" | "shimmer";
77
+ readonly radius?: import("@stealthscale/theme/authoring").Corner;
78
+ }>;
79
+ /**
80
+ * Describes what a skeleton takes: the variants its recipe offers, and everything a styled div
81
+ * takes.
82
+ */
83
+ type SkeletonProps = ComponentProps<typeof Skeleton>;
84
+ //#endregion
85
+ //#region src/skeleton-text/skeleton-text.d.ts
86
+ /**
87
+ * Draws the column the bars sit in.
88
+ */
89
+ declare const Column: import("@stealthscale/theme").StyledComponent<"div", {}>;
90
+ /**
91
+ * Describes what a paragraph of skeleton takes.
92
+ */
93
+ interface SkeletonTextProps extends ComponentProps<typeof Column> {
94
+ /**
95
+ * How many lines of text it stands in for.
96
+ */
97
+ readonly lines?: number | undefined;
98
+ /**
99
+ * How each bar moves while it waits, which every bar takes together.
100
+ */
101
+ readonly motion?: SkeletonProps["motion"] | undefined;
102
+ /**
103
+ * The corner each bar is drawn with.
104
+ */
105
+ readonly radius?: SkeletonProps["radius"] | undefined;
106
+ }
107
+ /**
108
+ * Stands in for a paragraph of text that has not arrived.
109
+ *
110
+ * @param props - The column's own, plus the count and what each bar is drawn like.
111
+ * @returns The column, holding one bar per line.
112
+ */
113
+ export declare function SkeletonText({ lines, motion, radius, ...rest }: SkeletonTextProps): ReactElement;
114
+ //#endregion
115
+ //#region src/skeleton/context.d.ts
116
+ /**
117
+ * Binds the skeleton's recipe to the element that draws it.
118
+ *
119
+ * @remarks
120
+ * Apart from the recipe, because an application's compiler reads the recipe at build time and
121
+ * the binding needs the runtime. A recipe file that also bound one would put the runtime behind
122
+ * every compiler configuration that reads it.
123
+ */
124
+ /**
125
+ * Binds the recipe once, for the skeleton, for the lines a paragraph of them draws, and for
126
+ * whatever sets their variants from above.
127
+ */
128
+ declare const PropsProvider: import("react").Provider<import("@stealthscale/theme").DataAttrs & Partial<{
129
+ readonly loading?: boolean;
130
+ readonly motion?: "none" | "pulse" | "shimmer";
131
+ readonly radius?: import("@stealthscale/theme/authoring").Corner;
132
+ }>>, withContext: <Tag extends import("react").ElementType>(Component: Tag, options?: import("@stealthscale/theme").JsxFactoryOptions<import("@stealthscale/theme").ComponentProps<Tag> & Partial<{
133
+ readonly loading?: boolean;
134
+ readonly motion?: "none" | "pulse" | "shimmer";
135
+ readonly radius?: import("@stealthscale/theme/authoring").Corner;
136
+ }>> | undefined) => import("@stealthscale/theme").StyledComponent<Tag, {
137
+ readonly loading?: boolean;
138
+ readonly motion?: "none" | "pulse" | "shimmer";
139
+ readonly radius?: import("@stealthscale/theme/authoring").Corner;
140
+ }>;
141
+ //#endregion
142
+ export { index_d_exports as EmptyState, type SkeletonProps, PropsProvider as SkeletonPropsProvider, type SkeletonTextProps, PropsProvider$1 as SkeletonTextPropsProvider };
package/dist/index.js ADDED
@@ -0,0 +1,177 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { n as recipe$1, r as recipe, t as recipe$2 } from "./recipe-0Xo90j3-.js";
3
+ import "react";
4
+ import { createRecipeContext, createSlotRecipeContext } from "@stealthscale/theme";
5
+ import { c } from "react/compiler-runtime";
6
+ import { jsx } from "react/jsx-runtime";
7
+ //#region src/empty-state/context.ts
8
+ /**
9
+ * Binds the empty state's recipe to the elements that draw its parts.
10
+ *
11
+ * @remarks
12
+ * Apart from the recipe, because an application's compiler reads the recipe at build time and
13
+ * the binding needs the runtime.
14
+ */
15
+ /**
16
+ * Binds the recipe once. The root provides the variants and every other part reads them.
17
+ */
18
+ const { withContext: withContext$2, withProvider } = createSlotRecipeContext(recipe);
19
+ //#endregion
20
+ //#region src/empty-state/content.ts
21
+ /**
22
+ * Centres what it holds, in a column, at the gap its size states.
23
+ */
24
+ const Content = withContext$2("div", "content");
25
+ //#endregion
26
+ //#region src/empty-state/description.ts
27
+ /**
28
+ * Draws the explanation, quieter than the title and at one size whatever the panel's is.
29
+ */
30
+ const Description = withContext$2("p", "description");
31
+ //#endregion
32
+ //#region src/empty-state/indicator.ts
33
+ /**
34
+ * Draws the mark at the box its size states.
35
+ */
36
+ const Indicator = withContext$2("div", "indicator");
37
+ //#endregion
38
+ //#region src/empty-state/root.ts
39
+ /**
40
+ * Draws the panel and sets the size every part below it reads.
41
+ */
42
+ const Root = withProvider("div", "root");
43
+ //#endregion
44
+ //#region src/empty-state/title.ts
45
+ /**
46
+ * Draws the title at the size the panel states.
47
+ */
48
+ const Title = withContext$2("h2", "title");
49
+ //#endregion
50
+ //#region src/empty-state/index.ts
51
+ var empty_state_exports = /* @__PURE__ */ __exportAll({
52
+ Content: () => Content,
53
+ Description: () => Description,
54
+ Indicator: () => Indicator,
55
+ Root: () => Root,
56
+ Title: () => Title
57
+ });
58
+ //#endregion
59
+ //#region src/skeleton-text/context.ts
60
+ /**
61
+ * Binds the skeleton paragraph's recipe to the element that draws it.
62
+ *
63
+ * @remarks
64
+ * Apart from the recipe, because an application's compiler reads the recipe at build time and
65
+ * the binding needs the runtime.
66
+ */
67
+ /**
68
+ * Binds the recipe once, for the column the bars are drawn in.
69
+ */
70
+ const { PropsProvider: PropsProvider$1, withContext: withContext$1 } = createRecipeContext(recipe$1);
71
+ //#endregion
72
+ //#region src/skeleton/context.ts
73
+ /**
74
+ * Binds the skeleton's recipe to the element that draws it.
75
+ *
76
+ * @remarks
77
+ * Apart from the recipe, because an application's compiler reads the recipe at build time and
78
+ * the binding needs the runtime. A recipe file that also bound one would put the runtime behind
79
+ * every compiler configuration that reads it.
80
+ */
81
+ /**
82
+ * Binds the recipe once, for the skeleton, for the lines a paragraph of them draws, and for
83
+ * whatever sets their variants from above.
84
+ */
85
+ const { PropsProvider, withContext } = createRecipeContext(recipe$2);
86
+ //#endregion
87
+ //#region src/skeleton/skeleton.ts
88
+ /**
89
+ * Stands in for content that has not arrived, taking the box of whatever it wraps.
90
+ */
91
+ const Skeleton = withContext("div");
92
+ //#endregion
93
+ //#region src/skeleton-text/skeleton-text.tsx
94
+ /**
95
+ * Draws the column the bars sit in.
96
+ */
97
+ const Column = withContext$1("div");
98
+ /**
99
+ * Stands in for a paragraph of text that has not arrived.
100
+ *
101
+ * @param props - The column's own, plus the count and what each bar is drawn like.
102
+ * @returns The column, holding one bar per line.
103
+ */
104
+ function SkeletonText(t0) {
105
+ const $ = c(21);
106
+ if ($[0] !== "3e498a8a62cfbdc6b1a8f49a0d7face7f241ed07bd456e29510103fe19bfc79d") {
107
+ for (let $i = 0; $i < 21; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
108
+ $[0] = "3e498a8a62cfbdc6b1a8f49a0d7face7f241ed07bd456e29510103fe19bfc79d";
109
+ }
110
+ let motion;
111
+ let radius;
112
+ let rest;
113
+ let t1;
114
+ if ($[1] !== t0) {
115
+ ({lines: t1, motion, radius, ...rest} = t0);
116
+ $[1] = t0;
117
+ $[2] = motion;
118
+ $[3] = radius;
119
+ $[4] = rest;
120
+ $[5] = t1;
121
+ } else {
122
+ motion = $[2];
123
+ radius = $[3];
124
+ rest = $[4];
125
+ t1 = $[5];
126
+ }
127
+ const lines = t1 === void 0 ? 3 : t1;
128
+ let t2;
129
+ if ($[6] !== motion) {
130
+ t2 = motion === void 0 ? {} : { motion };
131
+ $[6] = motion;
132
+ $[7] = t2;
133
+ } else t2 = $[7];
134
+ let t3;
135
+ if ($[8] !== radius) {
136
+ t3 = radius === void 0 ? {} : { radius };
137
+ $[8] = radius;
138
+ $[9] = t3;
139
+ } else t3 = $[9];
140
+ let t4;
141
+ if ($[10] !== t2 || $[11] !== t3) {
142
+ t4 = {
143
+ ...t2,
144
+ ...t3
145
+ };
146
+ $[10] = t2;
147
+ $[11] = t3;
148
+ $[12] = t4;
149
+ } else t4 = $[12];
150
+ const drawn = t4;
151
+ let t5;
152
+ if ($[13] !== drawn || $[14] !== lines) {
153
+ let t6;
154
+ if ($[16] !== drawn) {
155
+ t6 = (_, at) => /* @__PURE__ */ jsx(Skeleton, { ...drawn }, at);
156
+ $[16] = drawn;
157
+ $[17] = t6;
158
+ } else t6 = $[17];
159
+ t5 = Array.from({ length: Math.max(lines, 1) }, t6);
160
+ $[13] = drawn;
161
+ $[14] = lines;
162
+ $[15] = t5;
163
+ } else t5 = $[15];
164
+ let t6;
165
+ if ($[18] !== rest || $[19] !== t5) {
166
+ t6 = /* @__PURE__ */ jsx(Column, {
167
+ ...rest,
168
+ children: t5
169
+ });
170
+ $[18] = rest;
171
+ $[19] = t5;
172
+ $[20] = t6;
173
+ } else t6 = $[20];
174
+ return t6;
175
+ }
176
+ //#endregion
177
+ export { empty_state_exports as EmptyState, Skeleton, PropsProvider as SkeletonPropsProvider, SkeletonText, PropsProvider$1 as SkeletonTextPropsProvider };
@@ -0,0 +1,162 @@
1
+ import { cornerVariants, defineRecipe, defineSlotRecipe, gapSizes, iconSizes, insetSizes, onSlots, textSizes } from "@stealthscale/theme/authoring";
2
+ //#region src/empty-state/recipe.ts
3
+ /**
4
+ * States what an empty state is: the panel a page draws where there is nothing to show, holding a
5
+ * mark, a heading and a line saying what would be here.
6
+ *
7
+ * @remarks
8
+ * Five parts, because each is styled and a caller composes them in whatever order a page wants.
9
+ * The root is the panel, the content centres what is inside it, the indicator draws the mark, and
10
+ * the title and the description carry the words.
11
+ * One axis moves all of them together. The room inside the panel, the gap in the content, the box
12
+ * of the mark and the size of the title each read the scale of the same name, so a small empty
13
+ * state in a side panel and a large one filling a page are one name apart. The description holds
14
+ * its size, because a line of explanation is read at the size the rest of the page is read at
15
+ * however big the panel is.
16
+ */
17
+ /**
18
+ * Draws a centred panel at the middle size until a caller says otherwise.
19
+ */
20
+ const recipe$2 = defineSlotRecipe({
21
+ base: {
22
+ content: {
23
+ alignItems: "center",
24
+ display: "flex",
25
+ flexDirection: "column",
26
+ justifyContent: "center",
27
+ textAlign: "center"
28
+ },
29
+ description: {
30
+ color: "fg.muted",
31
+ textStyle: "body.sm"
32
+ },
33
+ indicator: {
34
+ "& svg": { boxSize: "100%" },
35
+ alignItems: "center",
36
+ color: "fg.muted",
37
+ display: "flex",
38
+ justifyContent: "center"
39
+ },
40
+ root: {
41
+ alignItems: "center",
42
+ display: "flex",
43
+ justifyContent: "center",
44
+ width: "full"
45
+ },
46
+ title: { fontWeight: "semibold" }
47
+ },
48
+ className: "empty-state",
49
+ defaultVariants: { size: "md" },
50
+ jsx: [/^EmptyState(\.\w+)?$/u],
51
+ slots: [
52
+ "root",
53
+ "content",
54
+ "indicator",
55
+ "title",
56
+ "description"
57
+ ],
58
+ variants: {
59
+ /**
60
+ * How much room the panel takes, which every part steps with.
61
+ */
62
+ size: onSlots({
63
+ content: gapSizes(),
64
+ indicator: iconSizes(),
65
+ root: insetSizes(),
66
+ title: textSizes("heading")
67
+ }) }
68
+ });
69
+ //#endregion
70
+ //#region src/skeleton-text/recipe.ts
71
+ /**
72
+ * States what a paragraph of skeleton is: a column of bars standing in for lines of text that have
73
+ * not arrived.
74
+ *
75
+ * @remarks
76
+ * Every length here is read off the line the bars stand in for. A bar is one line tall and the
77
+ * space between two is half a line, so a column of stand-ins occupies what the real paragraph
78
+ * will occupy and the page does not jump when the words land. Nothing states a size of its own,
79
+ * which is what lets a caller drop a paragraph of stand-ins wherever text is read and have it
80
+ * come out the size of that text.
81
+ * The last bar of several is short. A paragraph rarely fills its final line, and a block of bars
82
+ * all the same width reads as a table rather than as prose.
83
+ */
84
+ /**
85
+ * Draws a column of bars, each the height of the line it stands in for.
86
+ */
87
+ const recipe$1 = defineRecipe({
88
+ base: {
89
+ "& > *": { height: "1lh" },
90
+ "& > *:last-child:not(:only-child)": { maxWidth: "80%" },
91
+ display: "flex",
92
+ flexDirection: "column",
93
+ gap: "0.5lh",
94
+ width: "full"
95
+ },
96
+ className: "skeleton-text",
97
+ jsx: [/^SkeletonText$/u]
98
+ });
99
+ //#endregion
100
+ //#region src/skeleton/recipe.ts
101
+ /**
102
+ * States what a skeleton is: a box standing in for content that has not arrived, drawn in one of
103
+ * the theme's own motions and revealed once the content does.
104
+ *
105
+ * @remarks
106
+ * A skeleton wraps the content it stands in for rather than replacing it, so a caller writes one
107
+ * tree and flips one prop. While it is loading it takes the content's own box and hides
108
+ * everything inside it, which is what makes the stand-in the size of the thing it stands in for
109
+ * without anybody stating a width. Once it has loaded it fades the content in and gets out of
110
+ * the way.
111
+ * Every motion is an animation style the theme owns, so a reader who asked for less motion is
112
+ * answered once in the theme rather than in every recipe. Nothing here states a colour, a length
113
+ * or a duration of its own.
114
+ */
115
+ /**
116
+ * Draws a pulsing stand-in at the middle corner until a caller says otherwise.
117
+ */
118
+ const recipe = defineRecipe({
119
+ base: {},
120
+ className: "skeleton",
121
+ defaultVariants: {
122
+ loading: true,
123
+ motion: "pulse",
124
+ radius: "l2"
125
+ },
126
+ jsx: [/^Skeleton$/u],
127
+ variants: {
128
+ /**
129
+ * Whether the content it stands in for has arrived.
130
+ */
131
+ loading: {
132
+ false: { animationStyle: "fade.in" },
133
+ true: {
134
+ "&::before, &::after, *": { visibility: "hidden" },
135
+ backgroundClip: "padding-box",
136
+ boxShadow: "none",
137
+ color: "transparent",
138
+ flexShrink: "0",
139
+ pointerEvents: "none",
140
+ userSelect: "none"
141
+ }
142
+ },
143
+ /**
144
+ * How it moves while it waits.
145
+ */
146
+ motion: {
147
+ none: { animation: "none" },
148
+ pulse: {
149
+ animationStyle: "pulse",
150
+ background: "bg.emphasized"
151
+ },
152
+ shimmer: {
153
+ animationStyle: "shimmer",
154
+ backgroundImage: "linear-gradient(270deg, {colors.bg.muted}, {colors.bg.emphasized})",
155
+ backgroundSize: "400% 100%"
156
+ }
157
+ },
158
+ radius: cornerVariants()
159
+ }
160
+ });
161
+ //#endregion
162
+ export { recipe$1 as n, recipe$2 as r, recipe as t };
@@ -0,0 +1,13 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true
8
+ });
9
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
+ return target;
11
+ };
12
+ //#endregion
13
+ export { __exportAll as t };
@@ -0,0 +1,12 @@
1
+ //#region src/theme.d.ts
2
+ /**
3
+ * Publishes the preset that registers every recipe in this package, for an application's compiler
4
+ * to install.
5
+ *
6
+ * @remarks
7
+ * The list is written by hand. The package's own specification reports a recipe file the list
8
+ * leaves out, so no generator runs here.
9
+ */
10
+ declare const _default: import("@stealthscale/theme/authoring").Preset;
11
+ //#endregion
12
+ export { _default as default };
package/dist/theme.js ADDED
@@ -0,0 +1,23 @@
1
+ import { n as recipe$1, r as recipe$2, t as recipe } from "./recipe-0Xo90j3-.js";
2
+ import { definePreset } from "@stealthscale/theme/authoring";
3
+ //#region src/theme.ts
4
+ /**
5
+ * Publishes the preset that registers every recipe in this package, for an application's compiler
6
+ * to install.
7
+ *
8
+ * @remarks
9
+ * The list is written by hand. The package's own specification reports a recipe file the list
10
+ * leaves out, so no generator runs here.
11
+ */
12
+ var theme_default = definePreset({
13
+ name: "@stealthscale/component-feedback",
14
+ theme: { extend: {
15
+ recipes: {
16
+ skeleton: recipe,
17
+ skeletonText: recipe$1
18
+ },
19
+ slotRecipes: { emptyState: recipe$2 }
20
+ } }
21
+ });
22
+ //#endregion
23
+ export { theme_default as default };
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@stealthscale/component-feedback",
3
+ "version": "0.1.0",
4
+ "description": "Draws the system reporting on itself: what is loading, what went wrong, what state a thing is in.",
5
+ "keywords": [
6
+ "components",
7
+ "feedback",
8
+ "react",
9
+ "status"
10
+ ],
11
+ "homepage": "https://github.com/stealth-scale/config/tree/main/components/feedback#readme",
12
+ "bugs": "https://github.com/stealth-scale/config/issues",
13
+ "license": "MIT",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/stealth-scale/config.git",
17
+ "directory": "components/feedback"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "LICENSE",
22
+ "README.md"
23
+ ],
24
+ "type": "module",
25
+ "sideEffects": false,
26
+ "imports": {
27
+ "#*": "./src/*"
28
+ },
29
+ "exports": {
30
+ ".": "./dist/index.js",
31
+ "./theme": "./dist/theme.js",
32
+ "./package.json": "./package.json"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "devDependencies": {
38
+ "@arethetypeswrong/core": "^0.18.5",
39
+ "@rolldown/plugin-babel": "^0.2.4",
40
+ "@stealthscale/theme": "^0.3.0",
41
+ "@stealthscale/vite-config": "^0.6.0",
42
+ "@stealthscale/vite-config-react": "^0.8.0",
43
+ "@stealthscale/vite-config-theme": "^0.1.0",
44
+ "@stealthscale/vite-config-typescript": "^0.3.0",
45
+ "@testing-library/react": "^16.3.0",
46
+ "@types/react": "^19.3.0",
47
+ "@types/react-dom": "^19.3.0",
48
+ "babel-plugin-react-compiler": "^1.0.0",
49
+ "happy-dom": "^20.14.3",
50
+ "oxc-transform-react": "^0.149.0",
51
+ "publint": "^0.3.24",
52
+ "react": "^19.3.0",
53
+ "react-dom": "^19.3.0",
54
+ "typescript": "^7.0.2",
55
+ "vitest": "4.1.11"
56
+ },
57
+ "peerDependencies": {
58
+ "@stealthscale/theme": "^0.3.0",
59
+ "react": "^19.3.0"
60
+ },
61
+ "engines": {
62
+ "node": ">=26.0.0"
63
+ },
64
+ "scripts": {
65
+ "build": "vp pack",
66
+ "check": "vp check",
67
+ "test": "vp test"
68
+ }
69
+ }