Compare commits
67 Commits
update-nix
...
ke-docs-te
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc290fe59f | ||
|
|
89e18482ed | ||
|
|
a8217b5a32 | ||
|
|
bdd5de5628 | ||
|
|
61d8bfd0d1 | ||
|
|
b8d79c7fc2 | ||
|
|
fb25ab028b | ||
|
|
5b136ecaf0 | ||
|
|
d4733dbb0a | ||
|
|
bfb30251e6 | ||
|
|
33115f76b7 | ||
|
|
9e9208e699 | ||
|
|
6b3fd57174 | ||
|
|
3be5237cf6 | ||
|
|
368f80eaae | ||
|
|
4d7079534c | ||
|
|
7d4cf1c551 | ||
|
|
ea088b95e9 | ||
|
|
a7a37f5320 | ||
|
|
8bda4880a7 | ||
|
|
6eb83618c0 | ||
|
|
1fe3833779 | ||
|
|
e63f5c966e | ||
|
|
69241183ac | ||
|
|
0a7c65cd27 | ||
|
|
bd13eb3e23 | ||
|
|
1e5191a16c | ||
|
|
1e4bf0dd4e | ||
|
|
4d66dc59aa | ||
|
|
9a442c15e9 | ||
|
|
157af90a56 | ||
|
|
24b94965d8 | ||
|
|
46bcad9267 | ||
|
|
1aba0577dc | ||
|
|
383088af2d | ||
|
|
c3456c1f0c | ||
|
|
183de9209f | ||
|
|
1df5c5ff60 | ||
|
|
e55a3b4fc6 | ||
|
|
6ee4657da3 | ||
|
|
7294d8bcbe | ||
|
|
3fec5aa5b3 | ||
|
|
63e55b8631 | ||
|
|
dd771f8dd9 | ||
|
|
d31a4cc7d8 | ||
|
|
73d4cf51af | ||
|
|
d015218226 | ||
|
|
f50475fcfd | ||
|
|
ae5efd9e2f | ||
|
|
c2c2874e82 | ||
|
|
1f8c2a3722 | ||
|
|
50aa7eb0cf | ||
|
|
920b39a124 | ||
|
|
c159ef79d2 | ||
|
|
7a95b169c1 | ||
|
|
0c3fd40120 | ||
|
|
7268697dc5 | ||
|
|
ec395bada4 | ||
|
|
757552671c | ||
|
|
04b52d5bee | ||
|
|
ffeb8b892a | ||
|
|
26806b5750 | ||
|
|
6e70054566 | ||
|
|
93268e8592 | ||
|
|
a420c6ca25 | ||
|
|
69fd13a76f | ||
|
|
ab3f262c22 |
@@ -76,7 +76,6 @@ in
|
|||||||
cmd = "su - text-user -c 'pytest -s -n0 -m service_runner -p no:cacheprovider -o addopts="" ${cli.passthru.sourceWithTests}/clan_lib/llm'"
|
cmd = "su - text-user -c 'pytest -s -n0 -m service_runner -p no:cacheprovider -o addopts="" ${cli.passthru.sourceWithTests}/clan_lib/llm'"
|
||||||
print("Running tests with command: " + cmd)
|
print("Running tests with command: " + cmd)
|
||||||
|
|
||||||
|
|
||||||
# Run tests as text-user (environment variables are set automatically)
|
# Run tests as text-user (environment variables are set automatically)
|
||||||
peer1.succeed(cmd)
|
peer1.succeed(cmd)
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
options = {
|
options = {
|
||||||
host = lib.mkOption {
|
host = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
description = ''
|
description = ''
|
||||||
ip address or hostname (domain) of the machine
|
ip address or hostname (domain) of the machine
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -39,7 +39,6 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
|
|
||||||
# Collect searchDomains from all servers in this instance
|
# Collect searchDomains from all servers in this instance
|
||||||
allServerSearchDomains = lib.flatten (
|
allServerSearchDomains = lib.flatten (
|
||||||
lib.mapAttrsToList (_name: machineConfig: machineConfig.settings.certificate.searchDomains or [ ]) (
|
lib.mapAttrsToList (_name: machineConfig: machineConfig.settings.certificate.searchDomains or [ ]) (
|
||||||
@@ -47,7 +46,7 @@
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
# Merge client's searchDomains with all servers' searchDomains
|
# Merge client's searchDomains with all servers' searchDomains
|
||||||
searchDomains = uniqueStrings (settings.certificate.searchDomains ++ allServerSearchDomains);
|
searchDomains = lib.uniqueStrings (settings.certificate.searchDomains ++ allServerSearchDomains);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
clan.core.vars.generators.openssh-ca = lib.mkIf (searchDomains != [ ]) {
|
clan.core.vars.generators.openssh-ca = lib.mkIf (searchDomains != [ ]) {
|
||||||
|
|||||||
@@ -1,7 +1,23 @@
|
|||||||
|
🚧🚧🚧 Experimental 🚧🚧🚧
|
||||||
|
|
||||||
|
Use at your own risk.
|
||||||
|
|
||||||
|
We are still refining its interfaces, instability and breakages are expected.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
This module sets up [yggdrasil](https://yggdrasil-network.github.io/) across your clan.
|
This module sets up [yggdrasil](https://yggdrasil-network.github.io/) across your clan.
|
||||||
|
|
||||||
Yggdrasil is designed to be a future-proof and decentralised alternative to
|
Yggdrasil is designed to be a future-proof and decentralised alternative to the
|
||||||
the structured routing protocols commonly used today on the internet. Inside your clan, it will allow you to reach all of your machines.
|
structured routing protocols commonly used today on the internet. Inside your
|
||||||
|
clan, it will allow you to reach all of your machines.
|
||||||
|
|
||||||
|
If you have other services in your inventory which export peers (e.g. the
|
||||||
|
`internet` or the services) as [service
|
||||||
|
exports](https://docs.clan.lol/reference/options/clan_service/#exports), they
|
||||||
|
will be added as yggdrasil peers automatically. This allows using the stable
|
||||||
|
yggdrasil IPv6 address to refer to other hosts and letting yggdrasil decide on
|
||||||
|
the best routing based on available connections.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
|
|||||||
@@ -29,12 +29,13 @@
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
options.peers = lib.mkOption {
|
options.extraPeers = lib.mkOption {
|
||||||
type = lib.types.listOf lib.types.str;
|
type = lib.types.listOf lib.types.str;
|
||||||
default = [ ];
|
default = [ ];
|
||||||
description = ''
|
description = ''
|
||||||
Static peers to configure for this host.
|
Additional static peers to configure for this host. If you use a
|
||||||
If not set, local peers will be auto-discovered
|
VPN clan service, it will automatically be added as peers to other hosts.
|
||||||
|
Local peers are also auto-discovered and don't need to be added.
|
||||||
'';
|
'';
|
||||||
example = [
|
example = [
|
||||||
"tcp://192.168.1.1:6443"
|
"tcp://192.168.1.1:6443"
|
||||||
@@ -45,16 +46,67 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
perInstance =
|
perInstance =
|
||||||
{ settings, ... }:
|
{
|
||||||
|
settings,
|
||||||
|
roles,
|
||||||
|
exports,
|
||||||
|
...
|
||||||
|
}:
|
||||||
{
|
{
|
||||||
nixosModule =
|
nixosModule =
|
||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
|
lib,
|
||||||
|
clan-core,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
|
let
|
||||||
|
|
||||||
|
mkPeers = ip: [
|
||||||
|
# "tcp://${ip}:6443"
|
||||||
|
"quic://${ip}:6443"
|
||||||
|
"ws://${ip}:6443"
|
||||||
|
"tls://${ip}:6443"
|
||||||
|
];
|
||||||
|
|
||||||
|
select' = clan-core.inputs.nix-select.lib.select;
|
||||||
|
|
||||||
|
# TODO make it nicer @lassulus, @picnoir wants microlens
|
||||||
|
# Get a list of all exported IPs from all VPN modules
|
||||||
|
exportedPeerIPs = builtins.foldl' (
|
||||||
|
acc: e:
|
||||||
|
if e == { } then
|
||||||
|
acc
|
||||||
|
else
|
||||||
|
acc ++ (lib.flatten (builtins.filter (s: s != "") (lib.attrValues (select' "peers.*.plain" e))))
|
||||||
|
) [ ] (lib.attrValues (select' "instances.*.networking.?peers.*.host.?plain" exports));
|
||||||
|
|
||||||
|
# Construct a list of peers in yggdrasil format
|
||||||
|
exportedPeers = lib.flatten (map mkPeers exportedPeerIPs);
|
||||||
|
|
||||||
|
in
|
||||||
{
|
{
|
||||||
|
|
||||||
|
# Set <yggdrasil ip> <hostname>.<tld> for all hosts.
|
||||||
|
# Networking modules will then add themselves as peers, so we can
|
||||||
|
# always use this to resolve a host via the best possible route,
|
||||||
|
# doing fail-over if needed.
|
||||||
|
networking.extraHosts = lib.strings.concatStringsSep "\n" (
|
||||||
|
lib.filter (n: n != "") (
|
||||||
|
map (
|
||||||
|
name:
|
||||||
|
let
|
||||||
|
ipPath = "${config.clan.core.settings.directory}/vars/per-machine/${name}/yggdrasil/address/value";
|
||||||
|
in
|
||||||
|
if builtins.pathExists ipPath then
|
||||||
|
"${builtins.readFile ipPath} ${name}.${config.clan.core.settings.tld}"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
) (lib.attrNames roles.default.machines)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
clan.core.vars.generators.yggdrasil = {
|
clan.core.vars.generators.yggdrasil = {
|
||||||
|
|
||||||
files.privateKey = { };
|
files.privateKey = { };
|
||||||
@@ -99,7 +151,7 @@
|
|||||||
settings = {
|
settings = {
|
||||||
PrivateKeyPath = "/key";
|
PrivateKeyPath = "/key";
|
||||||
IfName = "ygg";
|
IfName = "ygg";
|
||||||
Peers = settings.peers;
|
Peers = lib.lists.unique (exportedPeers ++ settings.extraPeers);
|
||||||
MulticastInterfaces = [
|
MulticastInterfaces = [
|
||||||
# Ethernet is preferred over WIFI
|
# Ethernet is preferred over WIFI
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,13 @@
|
|||||||
roles.default.machines.peer1 = { };
|
roles.default.machines.peer1 = { };
|
||||||
roles.default.machines.peer2 = { };
|
roles.default.machines.peer2 = { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Peers are set form exports of the internet service
|
||||||
|
instances."internet" = {
|
||||||
|
module.name = "internet";
|
||||||
|
roles.default.machines.peer1.settings.host = "peer1";
|
||||||
|
roles.default.machines.peer2.settings.host = "peer2";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -140,9 +140,6 @@
|
|||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
|
||||||
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
(import ./shared.nix {
|
(import ./shared.nix {
|
||||||
@@ -159,7 +156,7 @@
|
|||||||
config = {
|
config = {
|
||||||
systemd.services.zerotier-inventory-autoaccept =
|
systemd.services.zerotier-inventory-autoaccept =
|
||||||
let
|
let
|
||||||
machines = uniqueStrings (
|
machines = lib.uniqueStrings (
|
||||||
(lib.optionals (roles ? moon) (lib.attrNames roles.moon.machines))
|
(lib.optionals (roles ? moon) (lib.attrNames roles.moon.machines))
|
||||||
++ (lib.optionals (roles ? controller) (lib.attrNames roles.controller.machines))
|
++ (lib.optionals (roles ? controller) (lib.attrNames roles.controller.machines))
|
||||||
++ (lib.optionals (roles ? peer) (lib.attrNames roles.peer.machines))
|
++ (lib.optionals (roles ? peer) (lib.attrNames roles.peer.machines))
|
||||||
|
|||||||
18
devFlake/flake.lock
generated
18
devFlake/flake.lock
generated
@@ -3,10 +3,10 @@
|
|||||||
"clan-core-for-checks": {
|
"clan-core-for-checks": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760361585,
|
"lastModified": 1761204206,
|
||||||
"narHash": "sha256-v4PnSmt1hXW4dSgVWxcd1ZeEBlhO7NksNRC5cX7L5iw=",
|
"narHash": "sha256-A4KDudGblln1yh8c95OVow2NRlHtbGZXr/pgNenyrNc=",
|
||||||
"ref": "main",
|
"ref": "main",
|
||||||
"rev": "7e7e58eb64ef61beb0a938a6622ec0122382131b",
|
"rev": "aabbe0dfac47b7cfbe2210bcb27fb7ecce93350f",
|
||||||
"shallow": true,
|
"shallow": true,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.clan.lol/clan/clan-core"
|
"url": "https://git.clan.lol/clan/clan-core"
|
||||||
@@ -105,11 +105,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs-dev": {
|
"nixpkgs-dev": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1761164809,
|
"lastModified": 1761544814,
|
||||||
"narHash": "sha256-3uM91Lx9WZomE6MMEBorJyEyBNiHWRIxza/GganDxew=",
|
"narHash": "sha256-t5f0A+2MtSWTfA6hzMNiotpIMGLlSQF2JnK9m6nkzIY=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "3d2db9755e7815937fb7b8f089fad9b44bc416d8",
|
"rev": "e5aa45ed6c45058ec109658b2b7352a9a062cdf3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -208,11 +208,11 @@
|
|||||||
"nixpkgs": []
|
"nixpkgs": []
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760945191,
|
"lastModified": 1761311587,
|
||||||
"narHash": "sha256-ZRVs8UqikBa4Ki3X4KCnMBtBW0ux1DaT35tgsnB1jM4=",
|
"narHash": "sha256-Msq86cR5SjozQGCnC6H8C+0cD4rnx91BPltZ9KK613Y=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "treefmt-nix",
|
"repo": "treefmt-nix",
|
||||||
"rev": "f56b1934f5f8fcab8deb5d38d42fd692632b47c2",
|
"rev": "2eddae033e4e74bf581c2d1dfa101f9033dbd2dc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -150,10 +150,61 @@ Those are very similar to NixOS VM tests, as in they run virtualized nixos machi
|
|||||||
As of now the container test driver is a downstream development in clan-core.
|
As of now the container test driver is a downstream development in clan-core.
|
||||||
Basically everything stated under the NixOS VM tests sections applies here, except some limitations.
|
Basically everything stated under the NixOS VM tests sections applies here, except some limitations.
|
||||||
|
|
||||||
Limitations:
|
### Using Container Tests vs VM Tests
|
||||||
|
|
||||||
- Cannot run in interactive mode, however while the container test runs, it logs a nsenter command that can be used to log into each of the container.
|
Container tests are **enabled by default** for all tests using the clan testing framework.
|
||||||
- setuid binaries don't work
|
They offer significant performance advantages over VM tests:
|
||||||
|
|
||||||
|
- **Faster startup**
|
||||||
|
- **Lower resource usage**: No full kernel boot or hardware emulation overhead
|
||||||
|
|
||||||
|
To control whether a test uses containers or VMs, use the `clan.test.useContainers` option:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
clan = {
|
||||||
|
directory = ./.;
|
||||||
|
test.useContainers = true; # Use containers (default)
|
||||||
|
# test.useContainers = false; # Use VMs instead
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use VM tests instead of container tests:**
|
||||||
|
|
||||||
|
- Testing kernel features, modules, or boot processes
|
||||||
|
- Testing hardware-specific features
|
||||||
|
- When you need full system isolation
|
||||||
|
|
||||||
|
### System Requirements for Container Tests
|
||||||
|
|
||||||
|
Container tests require the **`uid-range`** system feature** in the Nix sandbox.
|
||||||
|
This feature allows Nix to allocate a range of UIDs for containers to use, enabling `systemd-nspawn` containers to run properly inside the Nix build sandbox.
|
||||||
|
|
||||||
|
**Configuration:**
|
||||||
|
|
||||||
|
The `uid-range` feature requires the `auto-allocate-uids` setting to be enabled in your Nix configuration.
|
||||||
|
|
||||||
|
To verify or enable it, add to your `/etc/nix/nix.conf` or NixOS configuration:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
settings.experimental-features = [
|
||||||
|
"auto-allocate-uids"
|
||||||
|
];
|
||||||
|
|
||||||
|
nix.settings.auto-allocate-uids = true;
|
||||||
|
nix.settings.system-features = [ "uid-range" ];
|
||||||
|
```
|
||||||
|
|
||||||
|
**Technical details:**
|
||||||
|
|
||||||
|
- Container tests set `requiredSystemFeatures = [ "uid-range" ];` in their derivation (see `lib/test/container-test-driver/driver-module.nix:98`)
|
||||||
|
- Without this feature, containers cannot properly manage user namespaces and will fail to start
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
- Cannot run in interactive mode, however while the container test runs, it logs a nsenter command that can be used to log into each of the containers.
|
||||||
|
- Early implementation and limited by features.
|
||||||
|
|
||||||
### Where to find examples for NixOS container tests
|
### Where to find examples for NixOS container tests
|
||||||
|
|
||||||
|
|||||||
12
flake.lock
generated
12
flake.lock
generated
@@ -71,11 +71,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760721282,
|
"lastModified": 1761339987,
|
||||||
"narHash": "sha256-aAHphQbU9t/b2RRy2Eb8oMv+I08isXv2KUGFAFn7nCo=",
|
"narHash": "sha256-IUaawVwItZKi64IA6kF6wQCLCzpXbk2R46dHn8sHkig=",
|
||||||
"owner": "nix-darwin",
|
"owner": "nix-darwin",
|
||||||
"repo": "nix-darwin",
|
"repo": "nix-darwin",
|
||||||
"rev": "c3211fcd0c56c11ff110d346d4487b18f7365168",
|
"rev": "7cd9aac79ee2924a85c211d21fafd394b06a38de",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -181,11 +181,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1760945191,
|
"lastModified": 1761311587,
|
||||||
"narHash": "sha256-ZRVs8UqikBa4Ki3X4KCnMBtBW0ux1DaT35tgsnB1jM4=",
|
"narHash": "sha256-Msq86cR5SjozQGCnC6H8C+0cD4rnx91BPltZ9KK613Y=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "treefmt-nix",
|
"repo": "treefmt-nix",
|
||||||
"rev": "f56b1934f5f8fcab8deb5d38d42fd692632b47c2",
|
"rev": "2eddae033e4e74bf581c2d1dfa101f9033dbd2dc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -137,6 +137,12 @@ in
|
|||||||
default = { };
|
default = { };
|
||||||
type = types.submoduleWith {
|
type = types.submoduleWith {
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
|
self = throw ''
|
||||||
|
'self' is banned in the use of clan.services
|
||||||
|
Use 'exports' instead: https://docs.clan.lol/reference/options/clan_service/#exports
|
||||||
|
---
|
||||||
|
If you really need to used 'self' here, that makes the module less portable
|
||||||
|
'';
|
||||||
inherit (config.clanSettings)
|
inherit (config.clanSettings)
|
||||||
clan-core
|
clan-core
|
||||||
nixpkgs
|
nixpkgs
|
||||||
|
|||||||
@@ -7,14 +7,10 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (lib) mkOption types;
|
inherit (lib) mkOption types uniqueStrings;
|
||||||
inherit (types) attrsWith submoduleWith;
|
inherit (types) attrsWith submoduleWith;
|
||||||
|
|
||||||
errorContext = "Error context: ${lib.concatStringsSep "." _ctx}";
|
errorContext = "Error context: ${lib.concatStringsSep "." _ctx}";
|
||||||
# TODO:
|
|
||||||
# Remove once this gets merged upstream; performs in O(n*log(n) instead of O(n^2))
|
|
||||||
# https://github.com/NixOS/nixpkgs/pull/355616/files
|
|
||||||
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
|
|
||||||
/**
|
/**
|
||||||
Merges the role- and machine-settings using the role interface
|
Merges the role- and machine-settings using the role interface
|
||||||
|
|
||||||
@@ -81,6 +77,7 @@ let
|
|||||||
applySettings =
|
applySettings =
|
||||||
instanceName: instance:
|
instanceName: instance:
|
||||||
lib.mapAttrs (roleName: role: {
|
lib.mapAttrs (roleName: role: {
|
||||||
|
settings = config.instances.${instanceName}.roles.${roleName}.finalSettings.config;
|
||||||
machines = lib.mapAttrs (machineName: _v: {
|
machines = lib.mapAttrs (machineName: _v: {
|
||||||
settings =
|
settings =
|
||||||
config.instances.${instanceName}.roles.${roleName}.machines.${machineName}.finalSettings.config;
|
config.instances.${instanceName}.roles.${roleName}.machines.${machineName}.finalSettings.config;
|
||||||
@@ -158,6 +155,29 @@ in
|
|||||||
(
|
(
|
||||||
{ name, ... }@role:
|
{ name, ... }@role:
|
||||||
{
|
{
|
||||||
|
options.finalSettings = mkOption {
|
||||||
|
default = evalMachineSettings instance.name role.name null role.config.settings { };
|
||||||
|
type = types.raw;
|
||||||
|
description = ''
|
||||||
|
Final evaluated settings of the curent-machine
|
||||||
|
|
||||||
|
This contains the merged and evaluated settings of the role interface,
|
||||||
|
the role settings and the machine settings.
|
||||||
|
|
||||||
|
Type: 'configuration' as returned by 'lib.evalModules'
|
||||||
|
'';
|
||||||
|
apply = lib.warn ''
|
||||||
|
=== WANRING ===
|
||||||
|
'roles.<roleName>.settings' do not contain machine specific settings.
|
||||||
|
|
||||||
|
Prefer `machines.<machineName>.settings` instead. (i.e `perInstance: roles.<roleName>.machines.<machineName>.settings`)
|
||||||
|
|
||||||
|
If you have a use-case that requires access to the original role settings without machine overrides.
|
||||||
|
Contact us via matrix (https://matrix.to/#/#clan:clan.lol) or file an issue: https://git.clan.lol
|
||||||
|
|
||||||
|
This feature will be removed in the next release
|
||||||
|
'';
|
||||||
|
};
|
||||||
# instances.{instanceName}.roles.{roleName}.machines
|
# instances.{instanceName}.roles.{roleName}.machines
|
||||||
options.machines = mkOption {
|
options.machines = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
@@ -216,7 +236,7 @@ in
|
|||||||
|
|
||||||
options.extraModules = lib.mkOption {
|
options.extraModules = lib.mkOption {
|
||||||
default = [ ];
|
default = [ ];
|
||||||
type = types.listOf (types.either types.deferredModule types.str);
|
type = types.listOf types.deferredModule;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -483,6 +503,9 @@ in
|
|||||||
type = types.deferredModule;
|
type = types.deferredModule;
|
||||||
default = { };
|
default = { };
|
||||||
description = ''
|
description = ''
|
||||||
|
!!! Danger "Experimental Feature"
|
||||||
|
This feature is experimental and will change in the future.
|
||||||
|
|
||||||
export modules defined in 'perInstance'
|
export modules defined in 'perInstance'
|
||||||
mapped to their instance name
|
mapped to their instance name
|
||||||
|
|
||||||
@@ -611,6 +634,9 @@ in
|
|||||||
type = types.deferredModule;
|
type = types.deferredModule;
|
||||||
default = { };
|
default = { };
|
||||||
description = ''
|
description = ''
|
||||||
|
!!! Danger "Experimental Feature"
|
||||||
|
This feature is experimental and will change in the future.
|
||||||
|
|
||||||
export modules defined in 'perMachine'
|
export modules defined in 'perMachine'
|
||||||
mapped to their machine name
|
mapped to their machine name
|
||||||
|
|
||||||
@@ -712,6 +738,9 @@ in
|
|||||||
|
|
||||||
exports = mkOption {
|
exports = mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
|
!!! Danger "Experimental Feature"
|
||||||
|
This feature is experimental and will change in the future.
|
||||||
|
|
||||||
This services exports.
|
This services exports.
|
||||||
Gets merged with all other services exports.
|
Gets merged with all other services exports.
|
||||||
|
|
||||||
@@ -850,7 +879,11 @@ in
|
|||||||
instanceRes.nixosModule
|
instanceRes.nixosModule
|
||||||
]
|
]
|
||||||
++ (map (
|
++ (map (
|
||||||
s: if builtins.typeOf s == "string" then "${directory}/${s}" else s
|
s:
|
||||||
|
if builtins.typeOf s == "string" then
|
||||||
|
lib.warn "String types for 'extraModules' will be deprecated - ${s}" "${directory}/${s}"
|
||||||
|
else
|
||||||
|
lib.setDefaultModuleLocation "via inventory.instances.${instanceName}.roles.${roleName}" s
|
||||||
) instanceCfg.roles.${roleName}.extraModules);
|
) instanceCfg.roles.${roleName}.extraModules);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ in
|
|||||||
settings = { };
|
settings = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
settings = { };
|
||||||
};
|
};
|
||||||
peer = {
|
peer = {
|
||||||
machines = {
|
machines = {
|
||||||
@@ -146,6 +147,9 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
settings = {
|
||||||
|
timeout = "foo-peer";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
settings = {
|
settings = {
|
||||||
|
|||||||
@@ -102,18 +102,23 @@ in
|
|||||||
specificRoleSettings =
|
specificRoleSettings =
|
||||||
res.importedModulesEvaluated.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer;
|
res.importedModulesEvaluated.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer;
|
||||||
};
|
};
|
||||||
expected = rec {
|
expected = {
|
||||||
hasMachineSettings = true;
|
hasMachineSettings = true;
|
||||||
hasRoleSettings = false;
|
hasRoleSettings = true;
|
||||||
specificMachineSettings = {
|
specificMachineSettings = {
|
||||||
timeout = "foo-peer-jon";
|
timeout = "foo-peer-jon";
|
||||||
};
|
};
|
||||||
specificRoleSettings = {
|
specificRoleSettings = {
|
||||||
machines = {
|
machines = {
|
||||||
jon = {
|
jon = {
|
||||||
settings = specificMachineSettings;
|
settings = {
|
||||||
|
timeout = "foo-peer-jon";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
settings = {
|
||||||
|
timeout = "foo-peer";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
{
|
{
|
||||||
pkgs,
|
pkgs,
|
||||||
lib,
|
lib,
|
||||||
clan-core,
|
clanModule,
|
||||||
|
clanLib,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
eval = lib.evalModules {
|
eval = lib.evalModules {
|
||||||
modules = [
|
modules = [
|
||||||
clan-core.modules.clan.default
|
clanModule
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
evalDocs = pkgs.nixosOptionsDoc {
|
evalDocs = pkgs.nixosOptionsDoc {
|
||||||
options = eval.options;
|
options = eval.options;
|
||||||
warningsAreErrors = false;
|
warningsAreErrors = false;
|
||||||
transformOptions = clan-core.clanLib.docs.stripStorePathsFromDeclarations;
|
transformOptions = clanLib.docs.stripStorePathsFromDeclarations;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,26 @@
|
|||||||
{ self, lib, ... }:
|
{ self, lib, ... }:
|
||||||
|
let
|
||||||
|
clanModule = lib.modules.importApply ./default.nix { clan-core = self; };
|
||||||
|
in
|
||||||
{
|
{
|
||||||
flake.modules.clan.default = lib.modules.importApply ./default.nix { clan-core = self; };
|
flake.modules.clan.default = clanModule;
|
||||||
|
perSystem =
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
jsonDocs = import ./eval-docs.nix {
|
||||||
|
inherit
|
||||||
|
pkgs
|
||||||
|
lib
|
||||||
|
clanModule
|
||||||
|
;
|
||||||
|
clanLib = self.clanLib;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
legacyPackages.clan-options = jsonDocs.optionsJSON;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ in
|
|||||||
Global information about the clan.
|
Global information about the clan.
|
||||||
'';
|
'';
|
||||||
type = types.deferredModuleWith {
|
type = types.deferredModuleWith {
|
||||||
staticModules = [ ../inventoryClass/meta-interface.nix ];
|
staticModules = [ ../inventoryClass/meta.nix ];
|
||||||
};
|
};
|
||||||
default = { };
|
default = { };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -222,6 +222,18 @@ in
|
|||||||
inventoryClass =
|
inventoryClass =
|
||||||
let
|
let
|
||||||
flakeInputs = config.self.inputs;
|
flakeInputs = config.self.inputs;
|
||||||
|
# Compute the relative directory path
|
||||||
|
selfStr = toString config.self;
|
||||||
|
dirStr = toString directory;
|
||||||
|
relativeDirectory =
|
||||||
|
if selfStr == dirStr then
|
||||||
|
""
|
||||||
|
else if lib.hasPrefix selfStr dirStr then
|
||||||
|
lib.removePrefix (selfStr + "/") dirStr
|
||||||
|
else
|
||||||
|
# This shouldn't happen in normal usage, but can occur when
|
||||||
|
# the flake is copied (e.g., in tests). Fall back to empty string.
|
||||||
|
"";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
_module.args = {
|
_module.args = {
|
||||||
@@ -230,7 +242,12 @@ in
|
|||||||
imports = [
|
imports = [
|
||||||
../inventoryClass/default.nix
|
../inventoryClass/default.nix
|
||||||
{
|
{
|
||||||
inherit inventory directory flakeInputs;
|
inherit
|
||||||
|
inventory
|
||||||
|
directory
|
||||||
|
flakeInputs
|
||||||
|
relativeDirectory
|
||||||
|
;
|
||||||
exportsModule = config.exportsModule;
|
exportsModule = config.exportsModule;
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -1,24 +1,5 @@
|
|||||||
{
|
|
||||||
self,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
./clan/flake-module.nix
|
./clan/flake-module.nix
|
||||||
];
|
];
|
||||||
perSystem =
|
|
||||||
{
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
jsonDocs = import ./eval-docs.nix {
|
|
||||||
inherit pkgs lib;
|
|
||||||
clan-core = self;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
legacyPackages.clan-options = jsonDocs.optionsJSON;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,11 @@ let
|
|||||||
name:
|
name:
|
||||||
let
|
let
|
||||||
v = set.${name};
|
v = set.${name};
|
||||||
|
loc = path ++ [ name ];
|
||||||
in
|
in
|
||||||
if pred path v then
|
if pred loc v then
|
||||||
[
|
[
|
||||||
(lib.nameValuePair name (
|
(lib.nameValuePair name (if lib.isAttrs v then filterAttrsRecursive' loc pred v else v))
|
||||||
if lib.isAttrs v then filterAttrsRecursive' (path ++ [ name ]) pred v else v
|
|
||||||
))
|
|
||||||
]
|
]
|
||||||
else
|
else
|
||||||
[ ]
|
[ ]
|
||||||
@@ -56,8 +55,7 @@ let
|
|||||||
# Remove extraModules from serialization,
|
# Remove extraModules from serialization,
|
||||||
# identified by: prefix + pathLength + name
|
# identified by: prefix + pathLength + name
|
||||||
# inventory.instances.*.roles.*.extraModules
|
# inventory.instances.*.roles.*.extraModules
|
||||||
path: _value:
|
path: _value: !(lib.length path == 5 && ((lib.last path)) == "extraModules")
|
||||||
lib.length path <= 5 || lib.head path != "instances" || (lib.elemAt path 5) != "extraModules"
|
|
||||||
) exposedInventory;
|
) exposedInventory;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -83,6 +81,14 @@ in
|
|||||||
directory = mkOption {
|
directory = mkOption {
|
||||||
type = types.path;
|
type = types.path;
|
||||||
};
|
};
|
||||||
|
relativeDirectory = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
internal = true;
|
||||||
|
description = ''
|
||||||
|
The relative directory path from the flake root to the clan directory.
|
||||||
|
Empty string if directory equals the flake root.
|
||||||
|
'';
|
||||||
|
};
|
||||||
machines = mkOption {
|
machines = mkOption {
|
||||||
type = types.attrsOf (submodule ({
|
type = types.attrsOf (submodule ({
|
||||||
options = {
|
options = {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ in
|
|||||||
meta = lib.mkOption {
|
meta = lib.mkOption {
|
||||||
type = lib.types.submoduleWith {
|
type = lib.types.submoduleWith {
|
||||||
modules = [
|
modules = [
|
||||||
./meta-interface.nix
|
./meta.nix
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -359,7 +359,7 @@ in
|
|||||||
inherit clanLib;
|
inherit clanLib;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(import ./roles-interface.nix { })
|
(import ./role.nix { })
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,12 +44,6 @@ in
|
|||||||
description = ''
|
description = ''
|
||||||
List of additionally imported `.nix` expressions.
|
List of additionally imported `.nix` expressions.
|
||||||
|
|
||||||
Supported types:
|
|
||||||
|
|
||||||
- **Strings**: Interpreted relative to the 'directory' passed to `lib.clan`.
|
|
||||||
- **Paths**: should be relative to the current file.
|
|
||||||
- **Any**: Nix expression must be serializable to JSON.
|
|
||||||
|
|
||||||
!!! Note
|
!!! Note
|
||||||
**The import only happens if the machine is part of the service or role.**
|
**The import only happens if the machine is part of the service or role.**
|
||||||
|
|
||||||
@@ -73,15 +67,8 @@ in
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
'';
|
'';
|
||||||
apply = value: if lib.isString value then value else builtins.seq (builtins.toJSON value) value;
|
|
||||||
default = [ ];
|
default = [ ];
|
||||||
type = types.listOf (
|
type = types.listOf types.raw;
|
||||||
types.oneOf [
|
|
||||||
types.str
|
|
||||||
types.path
|
|
||||||
(types.attrsOf types.anything)
|
|
||||||
]
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
{
|
|
||||||
flakeInputs,
|
|
||||||
clanLib,
|
|
||||||
}:
|
|
||||||
{ lib, config, ... }:
|
|
||||||
let
|
|
||||||
inspectModule =
|
|
||||||
inputName: moduleName: module:
|
|
||||||
let
|
|
||||||
eval = clanLib.evalService {
|
|
||||||
modules = [ module ];
|
|
||||||
prefix = [
|
|
||||||
inputName
|
|
||||||
"clan"
|
|
||||||
"modules"
|
|
||||||
moduleName
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
manifest = eval.config.manifest;
|
|
||||||
roles = lib.mapAttrs (_n: v: { inherit (v) description; }) eval.config.roles;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.staticModules = lib.mkOption {
|
|
||||||
readOnly = true;
|
|
||||||
type = lib.types.raw;
|
|
||||||
|
|
||||||
apply = moduleSet: lib.mapAttrs (inspectModule "<clan-core>") moduleSet;
|
|
||||||
};
|
|
||||||
options.modulesPerSource = lib.mkOption {
|
|
||||||
# { sourceName :: { moduleName :: {} }}
|
|
||||||
readOnly = true;
|
|
||||||
type = lib.types.raw;
|
|
||||||
default =
|
|
||||||
let
|
|
||||||
inputsWithModules = lib.filterAttrs (_inputName: v: v ? clan.modules) flakeInputs;
|
|
||||||
in
|
|
||||||
lib.mapAttrs (
|
|
||||||
inputName: v: lib.mapAttrs (inspectModule inputName) v.clan.modules
|
|
||||||
) inputsWithModules;
|
|
||||||
};
|
|
||||||
options.moduleSchemas = lib.mkOption {
|
|
||||||
# { sourceName :: { moduleName :: { roleName :: Schema }}}
|
|
||||||
readOnly = true;
|
|
||||||
type = lib.types.raw;
|
|
||||||
default = lib.mapAttrs (
|
|
||||||
_inputName: moduleSet:
|
|
||||||
lib.mapAttrs (
|
|
||||||
_moduleName: module:
|
|
||||||
(clanLib.evalService {
|
|
||||||
modules = [ module ];
|
|
||||||
prefix = [ ];
|
|
||||||
}).config.result.api.schema
|
|
||||||
) moduleSet
|
|
||||||
) config.modulesPerSource;
|
|
||||||
};
|
|
||||||
options.templatesPerSource = lib.mkOption {
|
|
||||||
# { sourceName :: { moduleName :: {} }}
|
|
||||||
readOnly = true;
|
|
||||||
type = lib.types.raw;
|
|
||||||
default =
|
|
||||||
let
|
|
||||||
inputsWithTemplates = lib.filterAttrs (_inputName: v: v ? clan.templates) flakeInputs;
|
|
||||||
in
|
|
||||||
lib.mapAttrs (_inputName: v: lib.mapAttrs (_n: t: t) v.clan.templates) inputsWithTemplates;
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -107,8 +107,7 @@ in
|
|||||||
readOnly = true;
|
readOnly = true;
|
||||||
};
|
};
|
||||||
tld = lib.mkOption {
|
tld = lib.mkOption {
|
||||||
default = "clan";
|
type = types.strMatching "[a-z]+";
|
||||||
type = lib.types.str;
|
|
||||||
description = ''
|
description = ''
|
||||||
the TLD for the clan
|
the TLD for the clan
|
||||||
'';
|
'';
|
||||||
|
|||||||
1
pkgs/clan-app/ui/.gitignore
vendored
1
pkgs/clan-app/ui/.gitignore
vendored
@@ -2,5 +2,4 @@ app/api
|
|||||||
app/.fonts
|
app/.fonts
|
||||||
|
|
||||||
.vite
|
.vite
|
||||||
storybook-static
|
|
||||||
*.css.d.ts
|
*.css.d.ts
|
||||||
@@ -1,31 +1,20 @@
|
|||||||
import { mergeConfig } from "vite";
|
import type { StorybookConfig } from "storybook-solidjs-vite";
|
||||||
import type { StorybookConfig } from "@kachurun/storybook-solid-vite";
|
|
||||||
|
|
||||||
const config: StorybookConfig = {
|
export default {
|
||||||
framework: "@kachurun/storybook-solid-vite",
|
framework: "storybook-solidjs-vite",
|
||||||
stories: ["../src/**/*.mdx", "../src/**/*.stories.tsx"],
|
stories: ["../src/**/*.mdx", "../src/**/*.stories.tsx"],
|
||||||
addons: [
|
addons: [
|
||||||
"@storybook/addon-links",
|
"@storybook/addon-links",
|
||||||
"@storybook/addon-docs",
|
"@storybook/addon-docs",
|
||||||
"@storybook/addon-a11y",
|
"@storybook/addon-a11y",
|
||||||
|
{
|
||||||
|
name: "@storybook/addon-vitest",
|
||||||
|
options: {
|
||||||
|
cli: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
async viteFinal(config) {
|
|
||||||
return mergeConfig(config, {
|
|
||||||
define: { "process.env": {} },
|
|
||||||
});
|
|
||||||
},
|
|
||||||
core: {
|
core: {
|
||||||
disableTelemetry: true,
|
disableTelemetry: true,
|
||||||
},
|
},
|
||||||
typescript: {
|
} satisfies StorybookConfig;
|
||||||
reactDocgen: "react-docgen-typescript",
|
|
||||||
reactDocgenTypescriptOptions: {
|
|
||||||
shouldExtractLiteralValuesFromEnum: true,
|
|
||||||
// 👇 Default prop filter, which excludes props from node_modules
|
|
||||||
propFilter: (prop: any) =>
|
|
||||||
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Preview } from "@kachurun/storybook-solid-vite";
|
import type { Preview } from "storybook-solidjs-vite";
|
||||||
|
|
||||||
import "../src/index.css";
|
import "../src/index.css";
|
||||||
import "./preview.css";
|
import "./preview.css";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { setProjectAnnotations } from "@kachurun/storybook-solid-vite";
|
import { setProjectAnnotations } from "storybook-solidjs-vite";
|
||||||
import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
|
import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview";
|
||||||
|
|
||||||
import * as projectAnnotations from "./preview";
|
import * as projectAnnotations from "./preview";
|
||||||
|
|||||||
@@ -1,19 +1,9 @@
|
|||||||
{
|
{
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"gtk.webview.js",
|
"gtk.webview.js",
|
||||||
|
"src/api/clan/client-fetch.ts",
|
||||||
"stylelint.config.js",
|
"stylelint.config.js",
|
||||||
"util.ts",
|
|
||||||
"src/components/v2/**",
|
|
||||||
"api/**",
|
"api/**",
|
||||||
"tailwind/**"
|
"tailwind/**"
|
||||||
],
|
|
||||||
"ignoreDependencies": [
|
|
||||||
"@babel/plugin-syntax-import-attributes",
|
|
||||||
"@storybook/addon-viewport",
|
|
||||||
"@typescript-eslint/parser",
|
|
||||||
"@vitest/coverage-v8",
|
|
||||||
"http-server",
|
|
||||||
"playwright",
|
|
||||||
"wait-on"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
1582
pkgs/clan-app/ui/package-lock.json
generated
1582
pkgs/clan-app/ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,48 +12,35 @@
|
|||||||
"check": "tsc --noEmit --skipLibCheck && eslint ./src --fix",
|
"check": "tsc --noEmit --skipLibCheck && eslint ./src --fix",
|
||||||
"test": "vitest run --project unit --typecheck",
|
"test": "vitest run --project unit --typecheck",
|
||||||
"vite": "vite",
|
"vite": "vite",
|
||||||
"storybook": "storybook",
|
|
||||||
"knip": "knip --fix",
|
"knip": "knip --fix",
|
||||||
"storybook-dev": "storybook dev -p 6006",
|
"storybook": "storybook dev -p 6006",
|
||||||
"test-storybook": "vitest run --project storybook",
|
"test-storybook": "vitest run --project storybook",
|
||||||
"test-storybook-update-snapshots": "vitest run --project storybook --update"
|
"test-storybook-update-snapshots": "vitest run --project storybook --update"
|
||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-syntax-import-attributes": "^7.27.1",
|
|
||||||
"@eslint/js": "^9.3.0",
|
"@eslint/js": "^9.3.0",
|
||||||
"@kachurun/storybook-solid-vite": "^9.0.11",
|
|
||||||
"@linaria/core": "^6.3.0",
|
"@linaria/core": "^6.3.0",
|
||||||
"@sinonjs/fake-timers": "^14.0.0",
|
"@storybook/addon-a11y": "^9.1.13",
|
||||||
"@storybook/addon-a11y": "^9.0.8",
|
"@storybook/addon-docs": "^9.1.13",
|
||||||
"@storybook/addon-docs": "^9.0.8",
|
"@storybook/addon-links": "^9.1.13",
|
||||||
"@storybook/addon-links": "^9.0.8",
|
"@storybook/addon-vitest": "^9.1.13",
|
||||||
"@storybook/addon-viewport": "^9.0.8",
|
|
||||||
"@storybook/addon-vitest": "^9.0.8",
|
|
||||||
"@types/node": "^22.15.19",
|
"@types/node": "^22.15.19",
|
||||||
"@types/sinonjs__fake-timers": "^8.1.5",
|
|
||||||
"@types/three": "^0.176.0",
|
"@types/three": "^0.176.0",
|
||||||
"@typescript-eslint/parser": "^8.32.1",
|
|
||||||
"@vitest/browser": "^3.2.3",
|
"@vitest/browser": "^3.2.3",
|
||||||
"@vitest/coverage-v8": "^3.2.3",
|
|
||||||
"@wyw-in-js/vite": "^0.7.0",
|
"@wyw-in-js/vite": "^0.7.0",
|
||||||
"autoprefixer": "^10.4.19",
|
"autoprefixer": "^10.4.19",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"concurrently": "^9.1.2",
|
|
||||||
"eslint": "^9.27.0",
|
"eslint": "^9.27.0",
|
||||||
"eslint-plugin-tailwindcss": "^3.17.0",
|
"eslint-plugin-tailwindcss": "^3.17.0",
|
||||||
"eslint-plugin-unused-imports": "^4.1.4",
|
"eslint-plugin-unused-imports": "^4.1.4",
|
||||||
"extend": "^3.0.2",
|
|
||||||
"http-server": "^14.1.1",
|
|
||||||
"jsdom": "^26.1.0",
|
|
||||||
"knip": "^5.61.2",
|
"knip": "^5.61.2",
|
||||||
"markdown-to-jsx": "^7.7.10",
|
|
||||||
"playwright": "1.54.1",
|
"playwright": "1.54.1",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"postcss-url": "^10.1.3",
|
"postcss-url": "^10.1.3",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"storybook": "^9.0.8",
|
"storybook": "^9.1.13",
|
||||||
"swagger-ui-dist": "^5.26.2",
|
"storybook-solidjs-vite": "^9.0.3",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
"typescript": "^5.4.5",
|
"typescript": "^5.4.5",
|
||||||
"typescript-eslint": "^8.32.1",
|
"typescript-eslint": "^8.32.1",
|
||||||
@@ -62,11 +49,9 @@
|
|||||||
"vite-css-modules": "^1.10.0",
|
"vite-css-modules": "^1.10.0",
|
||||||
"vite-plugin-solid": "^2.8.2",
|
"vite-plugin-solid": "^2.8.2",
|
||||||
"vite-plugin-solid-svg": "^0.8.1",
|
"vite-plugin-solid-svg": "^0.8.1",
|
||||||
"vitest": "^3.2.3",
|
"vitest": "^3.2.4"
|
||||||
"wait-on": "^8.0.3"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@floating-ui/dom": "^1.6.8",
|
|
||||||
"@kobalte/core": "^0.13.10",
|
"@kobalte/core": "^0.13.10",
|
||||||
"@kobalte/tailwindcss": "^0.9.0",
|
"@kobalte/tailwindcss": "^0.9.0",
|
||||||
"@modular-forms/solid": "^0.25.1",
|
"@modular-forms/solid": "^0.25.1",
|
||||||
@@ -80,22 +65,6 @@
|
|||||||
"solid-js": "^1.9.7",
|
"solid-js": "^1.9.7",
|
||||||
"solid-toast": "^0.5.0",
|
"solid-toast": "^0.5.0",
|
||||||
"three": "^0.176.0",
|
"three": "^0.176.0",
|
||||||
"troika-three-text": "^0.52.4",
|
|
||||||
"valibot": "^1.1.0"
|
"valibot": "^1.1.0"
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@esbuild/darwin-arm64": "^0.25.4",
|
|
||||||
"@esbuild/darwin-x64": "^0.25.4",
|
|
||||||
"@esbuild/linux-arm64": "^0.25.4",
|
|
||||||
"@esbuild/linux-x64": "^0.25.4"
|
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"vite": {
|
|
||||||
"rollup": "npm:@rollup/wasm-node@^4.34.9"
|
|
||||||
},
|
|
||||||
"@rollup/rollup-darwin-x64": "npm:@rollup/wasm-node@^4.34.9",
|
|
||||||
"@rollup/rollup-linux-x64": "npm:@rollup/wasm-node@^4.34.9",
|
|
||||||
"@rollup/rollup-darwin-arm64": "npm:@rollup/wasm-node@^4.34.9",
|
|
||||||
"@rollup/rollup-linux-arm64": "npm:@rollup/wasm-node@^4.34.9"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Alert, AlertProps } from "@/src/components/Alert/Alert";
|
import { Alert, AlertProps } from "@/src/components/Alert/Alert";
|
||||||
import { expect, fn } from "storybook/test";
|
import { expect, fn } from "storybook/test";
|
||||||
import { StoryContext } from "@kachurun/storybook-solid-vite";
|
|
||||||
|
|
||||||
const AlertExamples = (props: AlertProps) => (
|
const AlertExamples = (props: AlertProps) => (
|
||||||
<div class="grid w-fit grid-cols-2 gap-8">
|
<div class="grid w-fit grid-cols-2 gap-8">
|
||||||
@@ -20,14 +19,14 @@ const AlertExamples = (props: AlertProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta: Meta<AlertProps> = {
|
const meta: Meta<typeof AlertExamples> = {
|
||||||
title: "Components/Alert",
|
title: "Components/Alert",
|
||||||
component: AlertExamples,
|
component: AlertExamples,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<AlertProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Info: Story = {
|
export const Info: Story = {
|
||||||
args: {
|
args: {
|
||||||
@@ -92,10 +91,13 @@ export const InfoDismiss: Story = {
|
|||||||
args: {
|
args: {
|
||||||
...Info.args,
|
...Info.args,
|
||||||
onDismiss: fn(),
|
onDismiss: fn(),
|
||||||
play: async ({ canvas, step, userEvent, args }: StoryContext) => {
|
},
|
||||||
await userEvent.click(canvas.getByRole("button"));
|
render(args) {
|
||||||
await expect(args.onDismiss).toHaveBeenCalled();
|
return <Alert {...args} />;
|
||||||
},
|
},
|
||||||
|
play: async ({ canvas, userEvent, args }) => {
|
||||||
|
await userEvent.click(canvas.getByRole("button"));
|
||||||
|
await expect(args.onDismiss).toHaveBeenCalled();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Button, ButtonProps } from "./Button";
|
import { Button, ButtonProps } from "./Button";
|
||||||
import { Component } from "solid-js";
|
import { Component } from "solid-js";
|
||||||
import { expect, fn, within } from "storybook/test";
|
import { expect, fn, within } from "storybook/test";
|
||||||
import { StoryContext } from "@kachurun/storybook-solid-vite";
|
|
||||||
|
|
||||||
const getCursorStyle = (el: Element) => window.getComputedStyle(el).cursor;
|
const getCursorStyle = (el: Element) => window.getComputedStyle(el).cursor;
|
||||||
|
|
||||||
@@ -202,7 +201,7 @@ const ButtonExamples: Component<ButtonProps> = (props) => (
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta: Meta<ButtonProps> = {
|
const meta: Meta<typeof ButtonExamples> = {
|
||||||
title: "Components/Button",
|
title: "Components/Button",
|
||||||
component: ButtonExamples,
|
component: ButtonExamples,
|
||||||
};
|
};
|
||||||
@@ -211,15 +210,13 @@ export default meta;
|
|||||||
|
|
||||||
type Story = StoryObj<ButtonProps>;
|
type Story = StoryObj<ButtonProps>;
|
||||||
|
|
||||||
const timeout = process.env.NODE_ENV === "test" ? 500 : 2000;
|
|
||||||
|
|
||||||
export const Primary: Story = {
|
export const Primary: Story = {
|
||||||
args: {
|
args: {
|
||||||
hierarchy: "primary",
|
hierarchy: "primary",
|
||||||
onClick: fn(),
|
onClick: fn(),
|
||||||
},
|
},
|
||||||
|
|
||||||
play: async ({ canvasElement, step, userEvent, args }: StoryContext) => {
|
play: async ({ canvasElement, step, userEvent, args }) => {
|
||||||
const canvas = within(canvasElement);
|
const canvas = within(canvasElement);
|
||||||
const buttons = await canvas.findAllByRole("button");
|
const buttons = await canvas.findAllByRole("button");
|
||||||
|
|
||||||
@@ -264,7 +261,7 @@ export const GhostPrimary: Story = {
|
|||||||
},
|
},
|
||||||
play: Primary.play,
|
play: Primary.play,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj) => (
|
(Story) => (
|
||||||
<div class="p-10 bg-def-3">
|
<div class="p-10 bg-def-3">
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ import Icon, { IconVariant } from "@/src/components/Icon/Icon";
|
|||||||
import { Loader } from "@/src/components/Loader/Loader";
|
import { Loader } from "@/src/components/Loader/Loader";
|
||||||
import { getInClasses, joinByDash, keepTruthy } from "@/src/util";
|
import { getInClasses, joinByDash, keepTruthy } from "@/src/util";
|
||||||
|
|
||||||
export type Size = "default" | "s" | "xs";
|
type Size = "default" | "s" | "xs";
|
||||||
export type Hierarchy = "primary" | "secondary";
|
type Hierarchy = "primary" | "secondary";
|
||||||
export type Elasticity = "default" | "fit";
|
type Elasticity = "default" | "fit";
|
||||||
|
|
||||||
export type Action = () => Promise<void>;
|
type Action = () => Promise<void>;
|
||||||
|
|
||||||
export interface ButtonProps
|
export interface ButtonProps
|
||||||
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { CubeConstruction } from "./CubeConstruction";
|
import { CubeConstruction } from "./CubeConstruction";
|
||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
|
|
||||||
const meta: Meta = {
|
const meta: Meta<typeof CubeConstruction> = {
|
||||||
title: "Components/CubeConstruction",
|
title: "Components/CubeConstruction",
|
||||||
component: CubeConstruction,
|
component: CubeConstruction,
|
||||||
globals: {
|
globals: {
|
||||||
@@ -12,7 +12,7 @@ const meta: Meta = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {},
|
args: {},
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Divider, DividerProps } from "@/src/components/Divider/Divider";
|
import { Divider } from "@/src/components/Divider/Divider";
|
||||||
|
|
||||||
const meta: Meta<DividerProps> = {
|
const meta: Meta<typeof Divider> = {
|
||||||
title: "Components/Divider",
|
title: "Components/Divider",
|
||||||
component: Divider,
|
component: Divider,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<DividerProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {};
|
export const Default: Story = {};
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export const Vertical: Story = {
|
|||||||
orientation: "vertical",
|
orientation: "vertical",
|
||||||
},
|
},
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: Story) => (
|
(Story) => (
|
||||||
<div class="h-32 w-full">
|
<div class="h-32 w-full">
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
@@ -43,5 +43,5 @@ export const VerticalInverted: Story = {
|
|||||||
inverted: true,
|
inverted: true,
|
||||||
...Vertical.args,
|
...Vertical.args,
|
||||||
},
|
},
|
||||||
decorators: [...Vertical.decorators],
|
decorators: Vertical.decorators,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { Checkbox, CheckboxProps } from "@/src/components/Form/Checkbox";
|
import { Checkbox, CheckboxProps } from "@/src/components/Form/Checkbox";
|
||||||
|
|
||||||
@@ -23,17 +23,17 @@ const Examples = (props: CheckboxProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof Examples> = {
|
||||||
title: "Components/Form/Checkbox",
|
title: "Components/Form/Checkbox",
|
||||||
component: Examples,
|
component: Examples,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<CheckboxProps>) => {
|
(Story, { args }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cx({
|
class={cx({
|
||||||
"w-[600px]": (context.args.orientation || "vertical") == "vertical",
|
"w-[600px]": (args.orientation || "vertical") == "vertical",
|
||||||
"w-[1024px]": context.args.orientation == "horizontal",
|
"w-[1024px]": args.orientation == "horizontal",
|
||||||
"bg-inv-acc-3": context.args.inverted,
|
"bg-inv-acc-3": args.inverted,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Story />
|
<Story />
|
||||||
@@ -41,7 +41,7 @@ const meta = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies Meta<CheckboxProps>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import {
|
import {
|
||||||
Fieldset,
|
Fieldset,
|
||||||
FieldsetFieldProps,
|
FieldsetFieldProps,
|
||||||
@@ -18,17 +18,17 @@ const FieldsetExamples = (props: FieldsetProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof FieldsetExamples> = {
|
||||||
title: "Components/Form/Fieldset",
|
title: "Components/Form/Fieldset",
|
||||||
component: FieldsetExamples,
|
component: FieldsetExamples,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<FieldsetProps>) => {
|
(Story, { args }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cx({
|
class={cx({
|
||||||
"w-[600px]": (context.args.orientation || "vertical") == "vertical",
|
"w-[600px]": (args.orientation || "vertical") == "vertical",
|
||||||
"w-[512px]": context.args.orientation == "horizontal",
|
"w-[512px]": args.orientation == "horizontal",
|
||||||
"bg-inv-acc-3": context.args.inverted,
|
"bg-inv-acc-3": args.inverted,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Story />
|
<Story />
|
||||||
@@ -36,7 +36,7 @@ const meta = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies Meta<FieldsetProps>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import {
|
import {
|
||||||
HostFileInput,
|
HostFileInput,
|
||||||
@@ -31,17 +31,17 @@ const Examples = (props: HostFileInputProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof Examples> = {
|
||||||
title: "Components/Form/HostFileInput",
|
title: "Components/Form/HostFileInput",
|
||||||
component: Examples,
|
component: Examples,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<HostFileInputProps>) => {
|
(Story, { args }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cx({
|
class={cx({
|
||||||
"w-[600px]": (context.args.orientation || "vertical") == "vertical",
|
"w-[600px]": (args.orientation || "vertical") == "vertical",
|
||||||
"w-[1024px]": context.args.orientation == "horizontal",
|
"w-[1024px]": args.orientation == "horizontal",
|
||||||
"bg-inv-acc-3": context.args.inverted,
|
"bg-inv-acc-3": args.inverted,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Story />
|
<Story />
|
||||||
@@ -49,7 +49,7 @@ const meta = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies Meta<HostFileInputProps>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ import styles from "./Label.module.css";
|
|||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { getInClasses } from "@/src/util";
|
import { getInClasses } from "@/src/util";
|
||||||
|
|
||||||
export type Size = "default" | "s";
|
type Size = "default" | "s";
|
||||||
|
|
||||||
export type LabelComponent =
|
type LabelComponent =
|
||||||
| typeof TextField.Label
|
| typeof TextField.Label
|
||||||
| typeof Checkbox.Label
|
| typeof Checkbox.Label
|
||||||
| typeof Combobox.Label
|
| typeof Combobox.Label
|
||||||
| typeof Select.Label;
|
| typeof Select.Label;
|
||||||
|
|
||||||
export type DescriptionComponent =
|
type DescriptionComponent =
|
||||||
| typeof TextField.Description
|
| typeof TextField.Description
|
||||||
| typeof Checkbox.Description
|
| typeof Checkbox.Description
|
||||||
| typeof Combobox.Description
|
| typeof Combobox.Description
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { MachineTags, MachineTagsProps } from "./MachineTags";
|
import { MachineTags } from "./MachineTags";
|
||||||
import { createForm, setValue } from "@modular-forms/solid";
|
import { createForm, setValue } from "@modular-forms/solid";
|
||||||
import { Button } from "../Button/Button";
|
import { Button } from "../Button/Button";
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof MachineTags> = {
|
||||||
title: "Components/MachineTags",
|
title: "Components/MachineTags",
|
||||||
component: MachineTags,
|
component: MachineTags,
|
||||||
} satisfies Meta<MachineTagsProps>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { CollectionNode } from "@kobalte/core";
|
|||||||
import styles from "./MachineTags.module.css";
|
import styles from "./MachineTags.module.css";
|
||||||
import { keepTruthy } from "@/src/util";
|
import { keepTruthy } from "@/src/util";
|
||||||
|
|
||||||
export interface MachineTag {
|
interface MachineTag {
|
||||||
value: string;
|
value: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { JSX, mergeProps } from "solid-js";
|
|||||||
|
|
||||||
import styles from "./Orienter.module.css";
|
import styles from "./Orienter.module.css";
|
||||||
|
|
||||||
export interface OrienterProps {
|
interface OrienterProps {
|
||||||
orientation?: "vertical" | "horizontal";
|
orientation?: "vertical" | "horizontal";
|
||||||
align?: "center" | "start";
|
align?: "center" | "start";
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { TextArea, TextAreaProps } from "./TextArea";
|
import { TextArea, TextAreaProps } from "./TextArea";
|
||||||
|
|
||||||
@@ -23,17 +23,17 @@ const Examples = (props: TextAreaProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof Examples> = {
|
||||||
title: "Components/Form/TextArea",
|
title: "Components/Form/TextArea",
|
||||||
component: Examples,
|
component: Examples,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<TextAreaProps>) => {
|
(Story, { args }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cx({
|
class={cx({
|
||||||
"w-[600px]": (context.args.orientation || "vertical") == "vertical",
|
"w-[600px]": (args.orientation || "vertical") == "vertical",
|
||||||
"w-[1024px]": context.args.orientation == "horizontal",
|
"w-[1024px]": args.orientation == "horizontal",
|
||||||
"bg-inv-acc-3": context.args.inverted,
|
"bg-inv-acc-3": args.inverted,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Story />
|
<Story />
|
||||||
@@ -41,7 +41,7 @@ const meta = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies Meta<TextAreaProps>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { TextInput, TextInputProps } from "@/src/components/Form/TextInput";
|
import { TextInput, TextInputProps } from "@/src/components/Form/TextInput";
|
||||||
import Icon from "../Icon/Icon";
|
import Icon from "../Icon/Icon";
|
||||||
@@ -25,17 +25,17 @@ const Examples = (props: TextInputProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof Examples> = {
|
||||||
title: "Components/Form/TextInput",
|
title: "Components/Form/TextInput",
|
||||||
component: Examples,
|
component: Examples,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<TextInputProps>) => {
|
(Story, { args }) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class={cx({
|
class={cx({
|
||||||
"w-[600px]": (context.args.orientation || "vertical") == "vertical",
|
"w-[600px]": (args.orientation || "vertical") == "vertical",
|
||||||
"w-[1024px]": context.args.orientation == "horizontal",
|
"w-[1024px]": args.orientation == "horizontal",
|
||||||
"bg-inv-acc-3": context.args.inverted,
|
"bg-inv-acc-3": args.inverted,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Story />
|
<Story />
|
||||||
@@ -43,7 +43,7 @@ const meta = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies Meta<TextInputProps>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryObj, StoryContext } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Component, For } from "solid-js";
|
import { Component, For } from "solid-js";
|
||||||
import Icon, { IconProps, IconVariant } from "./Icon";
|
import Icon, { IconProps, IconVariant } from "./Icon";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
@@ -57,12 +57,12 @@ const IconExamples: Component<IconProps> = (props) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta: Meta<IconProps> = {
|
const meta: Meta<typeof IconExamples> = {
|
||||||
title: "Components/Icon",
|
title: "Components/Icon",
|
||||||
component: IconExamples,
|
component: IconExamples,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<IconProps>) => (
|
(Story, { args }) => (
|
||||||
<div class={cx(context.args.inverted || false ? "bg-inv-acc-3" : "")}>
|
<div class={cx(args.inverted || false ? "bg-inv-acc-3" : "")}>
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@@ -71,7 +71,7 @@ const meta: Meta<IconProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<IconProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {};
|
export const Default: Story = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Loader, LoaderProps } from "@/src/components/Loader/Loader";
|
import { Loader, LoaderProps } from "@/src/components/Loader/Loader";
|
||||||
|
|
||||||
const LoaderExamples = (props: LoaderProps) => (
|
const LoaderExamples = (props: LoaderProps) => (
|
||||||
@@ -9,14 +9,14 @@ const LoaderExamples = (props: LoaderProps) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta: Meta<LoaderProps> = {
|
const meta: Meta<typeof LoaderExamples> = {
|
||||||
title: "Components/Loader",
|
title: "Components/Loader",
|
||||||
component: LoaderExamples,
|
component: LoaderExamples,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<LoaderProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Primary: Story = {
|
export const Primary: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { mergeProps } from "solid-js";
|
|||||||
import styles from "./Loader.module.css";
|
import styles from "./Loader.module.css";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
|
|
||||||
export type Hierarchy = "primary" | "secondary";
|
type Hierarchy = "primary" | "secondary";
|
||||||
|
|
||||||
export interface LoaderProps {
|
export interface LoaderProps {
|
||||||
hierarchy?: Hierarchy;
|
hierarchy?: Hierarchy;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { LoadingBar } from "./LoadingBar";
|
import { LoadingBar } from "./LoadingBar";
|
||||||
|
|
||||||
const meta: Meta = {
|
const meta: Meta<typeof LoadingBar> = {
|
||||||
title: "Components/LoadingBar",
|
title: "Components/LoadingBar",
|
||||||
component: LoadingBar,
|
component: LoadingBar,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<unknown>) => {
|
(Story) => {
|
||||||
return (
|
return (
|
||||||
<div class={"flex w-fit items-center justify-center bg-slate-500 p-10"}>
|
<div class={"flex w-fit items-center justify-center bg-slate-500 p-10"}>
|
||||||
<Story />
|
<Story />
|
||||||
@@ -17,6 +17,6 @@ const meta: Meta = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {};
|
export const Default: Story = {};
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { JSX } from "solid-js";
|
|||||||
import styles from "./LoadingBar.module.css";
|
import styles from "./LoadingBar.module.css";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
|
|
||||||
export type LoadingBarProps = JSX.HTMLAttributes<HTMLDivElement> & {};
|
type LoadingBarProps = JSX.HTMLAttributes<HTMLDivElement> & {};
|
||||||
export const LoadingBar = (props: LoadingBarProps) => (
|
export const LoadingBar = (props: LoadingBarProps) => (
|
||||||
<div {...props} class={cx(styles.loading_bar, props.class)} />
|
<div {...props} class={cx(styles.loading_bar, props.class)} />
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Component, For } from "solid-js";
|
import { Component, For } from "solid-js";
|
||||||
import { Logo, LogoProps, LogoVariant } from "./Logo";
|
import { Logo, LogoProps, LogoVariant } from "./Logo";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
@@ -11,12 +11,12 @@ const LogoExamples: Component<LogoProps> = (props) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta: Meta<LogoProps> = {
|
const meta: Meta<typeof LogoExamples> = {
|
||||||
title: "Components/Logo",
|
title: "Components/Logo",
|
||||||
component: LogoExamples,
|
component: LogoExamples,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<LogoProps>) => (
|
(Story, { args }) => (
|
||||||
<div class={cx(context.args.inverted || false ? "bg-inv-acc-3" : "")}>
|
<div class={cx(args.inverted || false ? "bg-inv-acc-3" : "")}>
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
@@ -25,7 +25,7 @@ const meta: Meta<LogoProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<LogoProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {};
|
export const Default: Story = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
import {
|
import { MachineStatus } from "@/src/components/MachineStatus/MachineStatus";
|
||||||
MachineStatus,
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
MachineStatusProps,
|
|
||||||
} from "@/src/components/MachineStatus/MachineStatus";
|
|
||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
|
||||||
|
|
||||||
const meta: Meta<MachineStatusProps> = {
|
const meta: Meta<typeof MachineStatus> = {
|
||||||
title: "Components/MachineStatus",
|
title: "Components/MachineStatus",
|
||||||
component: MachineStatus,
|
component: MachineStatus,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj) => (
|
(Story) => (
|
||||||
<div class="p-5 bg-inv-1">
|
<div class="p-5 bg-inv-1">
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
@@ -18,7 +15,7 @@ const meta: Meta<MachineStatusProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<MachineStatusProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Loading: Story = {
|
export const Loading: Story = {
|
||||||
args: {},
|
args: {},
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import { TagProps } from "@/src/components/Tag/Tag";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
|
||||||
import { fn } from "storybook/test";
|
import { fn } from "storybook/test";
|
||||||
import { Modal, ModalProps } from "@/src/components/Modal/Modal";
|
import { Modal } from "@/src/components/Modal/Modal";
|
||||||
import { Fieldset, FieldsetFieldProps } from "@/src/components/Form/Fieldset";
|
import { Fieldset, FieldsetFieldProps } from "@/src/components/Form/Fieldset";
|
||||||
import { TextInput } from "@/src/components/Form/TextInput";
|
import { TextInput } from "@/src/components/Form/TextInput";
|
||||||
import { TextArea } from "@/src/components/Form/TextArea";
|
import { TextArea } from "@/src/components/Form/TextArea";
|
||||||
import { Checkbox } from "@/src/components/Form/Checkbox";
|
import { Checkbox } from "@/src/components/Form/Checkbox";
|
||||||
import { Button } from "../Button/Button";
|
import { Button } from "../Button/Button";
|
||||||
|
|
||||||
const meta: Meta<ModalProps> = {
|
const meta: Meta<typeof Modal> = {
|
||||||
title: "Components/Modal",
|
title: "Components/Modal",
|
||||||
component: Modal,
|
component: Modal,
|
||||||
render: (args: ModalProps) => (
|
render: (args) => (
|
||||||
<Modal
|
<Modal
|
||||||
{...args}
|
{...args}
|
||||||
children={
|
children={
|
||||||
@@ -68,7 +67,7 @@ const meta: Meta<ModalProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<TagProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import Icon from "../Icon/Icon";
|
|||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { Dynamic } from "solid-js/web";
|
import { Dynamic } from "solid-js/web";
|
||||||
|
|
||||||
export interface ModalContextType {
|
interface ModalContextType {
|
||||||
portalRef: HTMLDivElement;
|
portalRef: HTMLDivElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import {
|
import { NavSection } from "@/src/components/NavSection/NavSection";
|
||||||
NavSection,
|
|
||||||
NavSectionProps,
|
|
||||||
} from "@/src/components/NavSection/NavSection";
|
|
||||||
|
|
||||||
const meta: Meta<NavSectionProps> = {
|
const meta: Meta<typeof NavSection> = {
|
||||||
title: "Components/NavSection",
|
title: "Components/NavSection",
|
||||||
component: NavSection,
|
component: NavSection,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj) => (
|
(Story) => (
|
||||||
<div class="w-96">
|
<div class="w-96">
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
@@ -18,7 +15,7 @@ const meta: Meta<NavSectionProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<NavSectionProps>;
|
type Story = StoryObj<typeof NavSection>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { CollectionNode } from "@kobalte/core/*";
|
|||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { Loader } from "../Loader/Loader";
|
import { Loader } from "../Loader/Loader";
|
||||||
|
|
||||||
export interface Option {
|
interface Option {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|||||||
@@ -1,24 +1,20 @@
|
|||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
|
|
||||||
import { Search, SearchProps } from "./Search";
|
import { Search } from "./Search";
|
||||||
import Icon from "../Icon/Icon";
|
import Icon from "../Icon/Icon";
|
||||||
import { Combobox } from "@kobalte/core/combobox";
|
import { Combobox } from "@kobalte/core/combobox";
|
||||||
import { Typography } from "../Typography/Typography";
|
import { Typography } from "../Typography/Typography";
|
||||||
import {
|
import { ItemRenderOptions, SearchMultiple } from "./MultipleSearch";
|
||||||
ItemRenderOptions,
|
|
||||||
SearchMultiple,
|
|
||||||
SearchMultipleProps,
|
|
||||||
} from "./MultipleSearch";
|
|
||||||
import { Show } from "solid-js";
|
import { Show } from "solid-js";
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof Search> = {
|
||||||
title: "Components/Search",
|
title: "Components/Search",
|
||||||
component: Search,
|
component: Search,
|
||||||
} satisfies Meta<SearchProps<unknown>>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<SearchProps<unknown>>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
// To test the virtualizer, we can generate a list of modules
|
// To test the virtualizer, we can generate a list of modules
|
||||||
function generateModules(count: number): Module[] {
|
function generateModules(count: number): Module[] {
|
||||||
@@ -107,7 +103,7 @@ export const Default: Story = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render: (args: SearchProps<Module>) => {
|
render: (args) => {
|
||||||
return (
|
return (
|
||||||
<div class="fixed bottom-10 left-1/2 mb-2 w-[30rem] -translate-x-1/2">
|
<div class="fixed bottom-10 left-1/2 mb-2 w-[30rem] -translate-x-1/2">
|
||||||
<Search<Module>
|
<Search<Module>
|
||||||
@@ -130,7 +126,7 @@ export const Loading: Story = {
|
|||||||
options: [],
|
options: [],
|
||||||
renderItem: () => <span></span>,
|
renderItem: () => <span></span>,
|
||||||
},
|
},
|
||||||
render: (args: SearchProps<Module>) => {
|
render: (args) => {
|
||||||
return (
|
return (
|
||||||
<div class="absolute bottom-1/3 w-3/4 px-3">
|
<div class="absolute bottom-1/3 w-3/4 px-3">
|
||||||
<Search<Module>
|
<Search<Module>
|
||||||
@@ -235,7 +231,7 @@ export const Multiple: Story = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render: (args: SearchMultipleProps<MachineOrTag>) => {
|
render: (args) => {
|
||||||
return (
|
return (
|
||||||
<div class="absolute bottom-1/3 w-3/4 px-3">
|
<div class="absolute bottom-1/3 w-3/4 px-3">
|
||||||
<SearchMultiple<MachineOrTag>
|
<SearchMultiple<MachineOrTag>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { CollectionNode } from "@kobalte/core/*";
|
|||||||
import { Loader } from "../Loader/Loader";
|
import { Loader } from "../Loader/Loader";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
|
|
||||||
export interface Option {
|
interface Option {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
|
|
||||||
import { TagSelect, TagSelectProps } from "./TagSelect";
|
import { TagSelect } from "./TagSelect";
|
||||||
import { Tag } from "../Tag/Tag";
|
import { Tag } from "../Tag/Tag";
|
||||||
import Icon from "../Icon/Icon";
|
import Icon from "../Icon/Icon";
|
||||||
import { createSignal } from "solid-js";
|
import { createSignal } from "solid-js";
|
||||||
|
|
||||||
const meta = {
|
const meta: Meta<typeof TagSelect> = {
|
||||||
title: "Components/Custom/SelectStepper",
|
title: "Components/Custom/SelectStepper",
|
||||||
component: TagSelect,
|
component: TagSelect,
|
||||||
} satisfies Meta<TagSelectProps<string>>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ interface Item {
|
|||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type Story = StoryObj<TagSelectProps<Item>>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
const Item = (item: Item) => (
|
const Item = (item: Item) => (
|
||||||
<Tag
|
<Tag
|
||||||
@@ -42,8 +42,8 @@ export const Default: Story = {
|
|||||||
{ value: "corge", label: "Corge" },
|
{ value: "corge", label: "Corge" },
|
||||||
{ value: "grault", label: "Grault" },
|
{ value: "grault", label: "Grault" },
|
||||||
],
|
],
|
||||||
} satisfies Partial<TagSelectProps<Item>>,
|
},
|
||||||
render: (args: TagSelectProps<Item>) => {
|
render: (args) => {
|
||||||
const [state, setState] = createSignal<Item[]>([]);
|
const [state, setState] = createSignal<Item[]>([]);
|
||||||
return (
|
return (
|
||||||
<TagSelect<Item>
|
<TagSelect<Item>
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
import { TagProps } from "@/src/components/Tag/Tag";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
|
||||||
|
|
||||||
import { Select, SelectProps } from "./Select";
|
import { Select } from "./Select";
|
||||||
import { Fieldset } from "../Form/Fieldset";
|
import { Fieldset } from "../Form/Fieldset";
|
||||||
|
|
||||||
// const meta: Meta<SelectProps> = {
|
const meta: Meta<typeof Select> = {
|
||||||
// title: "Components/Select",
|
|
||||||
// component: Select,
|
|
||||||
// };
|
|
||||||
const meta = {
|
|
||||||
title: "Components/Form/Select",
|
title: "Components/Form/Select",
|
||||||
component: Select,
|
component: Select,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext<SelectProps>) => {
|
(Story) => {
|
||||||
return (
|
return (
|
||||||
<div class={`w-[600px]`}>
|
<div class={`w-[600px]`}>
|
||||||
<Fieldset>
|
<Fieldset>
|
||||||
@@ -22,11 +17,11 @@ const meta = {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
} satisfies Meta<SelectProps>;
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<TagProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import cx from "classnames";
|
|||||||
import { useModalContext } from "../Modal/Modal";
|
import { useModalContext } from "../Modal/Modal";
|
||||||
import { keepTruthy } from "@/src/util";
|
import { keepTruthy } from "@/src/util";
|
||||||
|
|
||||||
export interface Option {
|
interface Option {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import {
|
import { createMemoryHistory, MemoryRouter, Route } from "@solidjs/router";
|
||||||
createMemoryHistory,
|
|
||||||
MemoryRouter,
|
|
||||||
Route,
|
|
||||||
RouteSectionProps,
|
|
||||||
} from "@solidjs/router";
|
|
||||||
import { Sidebar } from "@/src/components/Sidebar/Sidebar";
|
import { Sidebar } from "@/src/components/Sidebar/Sidebar";
|
||||||
import { Suspense } from "solid-js";
|
import { Suspense } from "solid-js";
|
||||||
import { addClanURI, resetStore } from "@/src/stores/clan";
|
import { addClanURI, resetStore } from "@/src/stores/clan";
|
||||||
@@ -106,7 +101,7 @@ const staticSections = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const meta: Meta<RouteSectionProps> = {
|
const meta: Meta<typeof Sidebar> = {
|
||||||
title: "Components/Sidebar",
|
title: "Components/Sidebar",
|
||||||
component: Sidebar,
|
component: Sidebar,
|
||||||
render: () => {
|
render: () => {
|
||||||
@@ -144,7 +139,7 @@ const meta: Meta<RouteSectionProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<RouteSectionProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
const mockFetcher = <K extends OperationNames>(
|
const mockFetcher = <K extends OperationNames>(
|
||||||
method: K,
|
method: K,
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import { SidebarBody } from "@/src/components/Sidebar/SidebarBody";
|
|||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { splitProps } from "solid-js";
|
import { splitProps } from "solid-js";
|
||||||
|
|
||||||
export interface LinkProps {
|
interface LinkProps {
|
||||||
path: string;
|
path: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SectionProps {
|
interface SectionProps {
|
||||||
title: string;
|
title: string;
|
||||||
links: LinkProps[];
|
links: LinkProps[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import {
|
import { SidebarPane } from "@/src/components/Sidebar/SidebarPane";
|
||||||
SidebarPane,
|
|
||||||
SidebarPaneProps,
|
|
||||||
} from "@/src/components/Sidebar/SidebarPane";
|
|
||||||
import { SidebarSection } from "./SidebarSection";
|
import { SidebarSection } from "./SidebarSection";
|
||||||
import { Divider } from "@/src/components/Divider/Divider";
|
import { Divider } from "@/src/components/Divider/Divider";
|
||||||
import { TextInput } from "@/src/components/Form/TextInput";
|
import { TextInput } from "@/src/components/Form/TextInput";
|
||||||
@@ -14,9 +11,6 @@ import { splitProps } from "solid-js";
|
|||||||
import { Typography } from "@/src/components/Typography/Typography";
|
import { Typography } from "@/src/components/Typography/Typography";
|
||||||
import { MachineTags } from "@/src/components/Form/MachineTags";
|
import { MachineTags } from "@/src/components/Form/MachineTags";
|
||||||
import { setValue } from "@modular-forms/solid";
|
import { setValue } from "@modular-forms/solid";
|
||||||
import { StoryContext } from "@kachurun/storybook-solid-vite";
|
|
||||||
|
|
||||||
type Story = StoryObj<SidebarPaneProps>;
|
|
||||||
|
|
||||||
const profiles = {
|
const profiles = {
|
||||||
ron: {
|
ron: {
|
||||||
@@ -28,18 +22,13 @@ const profiles = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const meta: Meta<SidebarPaneProps> = {
|
const meta: Meta<typeof SidebarPane> = {
|
||||||
title: "Components/SidebarPane",
|
title: "Components/SidebarPane",
|
||||||
component: SidebarPane,
|
component: SidebarPane,
|
||||||
decorators: [
|
|
||||||
(
|
|
||||||
Story: StoryObj<SidebarPaneProps>,
|
|
||||||
context: StoryContext<SidebarPaneProps>,
|
|
||||||
) =>
|
|
||||||
() => <Story {...context.args} />,
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
@@ -51,7 +40,7 @@ export const Default: Story = {
|
|||||||
},
|
},
|
||||||
// We have to provide children within a custom render function to ensure we aren't creating any reactivity outside the
|
// We have to provide children within a custom render function to ensure we aren't creating any reactivity outside the
|
||||||
// solid-js scope.
|
// solid-js scope.
|
||||||
render: (args: SidebarPaneProps) => (
|
render: (args) => (
|
||||||
<SidebarPane
|
<SidebarPane
|
||||||
{...args}
|
{...args}
|
||||||
children={
|
children={
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { JSX, Show } from "solid-js";
|
|||||||
import styles from "./SidebarSection.module.css";
|
import styles from "./SidebarSection.module.css";
|
||||||
import { Typography } from "@/src/components/Typography/Typography";
|
import { Typography } from "@/src/components/Typography/Typography";
|
||||||
|
|
||||||
export interface SidebarSectionProps {
|
interface SidebarSectionProps {
|
||||||
title: string;
|
title: string;
|
||||||
controls?: JSX.Element;
|
controls?: JSX.Element;
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { Button } from "@/src/components/Button/Button";
|
|||||||
import { Loader } from "../../components/Loader/Loader";
|
import { Loader } from "../../components/Loader/Loader";
|
||||||
import { SidebarSection } from "./SidebarSection";
|
import { SidebarSection } from "./SidebarSection";
|
||||||
|
|
||||||
export interface SidebarSectionFormProps<FormValues extends FieldValues> {
|
interface SidebarSectionFormProps<FormValues extends FieldValues> {
|
||||||
title: string;
|
title: string;
|
||||||
schema: GenericSchema<FormValues> | GenericSchemaAsync<FormValues>;
|
schema: GenericSchema<FormValues> | GenericSchemaAsync<FormValues>;
|
||||||
initialValues: PartialValues<FormValues>;
|
initialValues: PartialValues<FormValues>;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import styles from "./SidebarSectionInstall.module.css";
|
|||||||
import { Alert } from "../Alert/Alert";
|
import { Alert } from "../Alert/Alert";
|
||||||
import { useClanContext } from "@/src/routes/Clan/Clan";
|
import { useClanContext } from "@/src/routes/Clan/Clan";
|
||||||
|
|
||||||
export interface SidebarSectionInstallProps {
|
interface SidebarSectionInstallProps {
|
||||||
clanURI: string;
|
clanURI: string;
|
||||||
machineName: string;
|
machineName: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import styles from "./SidebarSectionInstall.module.css";
|
|||||||
import { UpdateModal } from "@/src/workflows/InstallMachine/UpdateMachine";
|
import { UpdateModal } from "@/src/workflows/InstallMachine/UpdateMachine";
|
||||||
import { useClanContext } from "@/src/routes/Clan/Clan";
|
import { useClanContext } from "@/src/routes/Clan/Clan";
|
||||||
|
|
||||||
export interface SidebarSectionUpdateProps {
|
interface SidebarSectionUpdateProps {
|
||||||
clanURI: string;
|
clanURI: string;
|
||||||
machineName: string;
|
machineName: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import { Tag, TagProps } from "@/src/components/Tag/Tag";
|
import { Tag } from "@/src/components/Tag/Tag";
|
||||||
import { Meta, type StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { fn } from "storybook/test";
|
import { fn } from "storybook/test";
|
||||||
import Icon from "../Icon/Icon";
|
import Icon from "../Icon/Icon";
|
||||||
|
|
||||||
const meta: Meta<TagProps> = {
|
const meta: Meta<typeof Tag> = {
|
||||||
title: "Components/Tag",
|
title: "Components/Tag",
|
||||||
component: Tag,
|
component: Tag,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<TagProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
@@ -43,7 +43,7 @@ export const WithAction: Story = {
|
|||||||
icon: IconAction,
|
icon: IconAction,
|
||||||
interactive: true,
|
interactive: true,
|
||||||
},
|
},
|
||||||
play: async ({ canvas, step, userEvent, args }: StoryContext) => {
|
play: async ({ canvas, step, userEvent, args }) => {
|
||||||
await userEvent.click(canvas.getByRole("button"));
|
await userEvent.click(canvas.getByRole("button"));
|
||||||
// await expect(args.icon.onClick).toHaveBeenCalled();
|
// await expect(args.icon.onClick).toHaveBeenCalled();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { TagGroup, TagGroupProps } from "@/src/components/TagGroup/TagGroup";
|
import { TagGroup } from "@/src/components/TagGroup/TagGroup";
|
||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
|
|
||||||
const meta: Meta<TagGroupProps> = {
|
const meta: Meta<typeof TagGroup> = {
|
||||||
title: "Components/TagGroup",
|
title: "Components/TagGroup",
|
||||||
component: TagGroup,
|
component: TagGroup,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj) => (
|
(Story) => (
|
||||||
/* for some reason w-x from tailwind was not working */
|
/* for some reason w-x from tailwind was not working */
|
||||||
<div style="width: 196px">
|
<div style="width: 196px">
|
||||||
<Story />
|
<Story />
|
||||||
@@ -16,7 +16,7 @@ const meta: Meta<TagGroupProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<TagGroupProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Toolbar, ToolbarProps } from "@/src/components/Toolbar/Toolbar";
|
import { Toolbar } from "@/src/components/Toolbar/Toolbar";
|
||||||
import { ToolbarButton } from "./ToolbarButton";
|
import { ToolbarButton } from "./ToolbarButton";
|
||||||
|
|
||||||
const meta: Meta<ToolbarProps> = {
|
const meta: Meta<typeof Toolbar> = {
|
||||||
title: "Components/Toolbar",
|
title: "Components/Toolbar",
|
||||||
component: Toolbar,
|
component: Toolbar,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<ToolbarProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
// We have to specify children inside a render function to avoid issues with reactivity outside a solid-js context.
|
// We have to specify children inside a render function to avoid issues with reactivity outside a solid-js context.
|
||||||
// @ts-expect-error: args in storybook is not typed correctly. This is a storybook issue.
|
|
||||||
render: (args) => (
|
render: (args) => (
|
||||||
<div class="flex h-[80vh]">
|
<div class="flex h-[80vh]">
|
||||||
<div class="mt-auto">
|
<div class="mt-auto">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Icon, { IconVariant } from "@/src/components/Icon/Icon";
|
|||||||
import type { JSX } from "solid-js";
|
import type { JSX } from "solid-js";
|
||||||
import { Tooltip } from "../Tooltip/Tooltip";
|
import { Tooltip } from "../Tooltip/Tooltip";
|
||||||
|
|
||||||
export interface ToolbarButtonProps
|
interface ToolbarButtonProps
|
||||||
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
icon: IconVariant;
|
icon: IconVariant;
|
||||||
description: JSX.Element;
|
description: JSX.Element;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Tooltip, TooltipProps } from "@/src/components/Tooltip/Tooltip";
|
import { Tooltip } from "@/src/components/Tooltip/Tooltip";
|
||||||
import { Typography } from "@/src/components/Typography/Typography";
|
import { Typography } from "@/src/components/Typography/Typography";
|
||||||
|
|
||||||
const meta: Meta<TooltipProps> = {
|
const meta: Meta<typeof Tooltip> = {
|
||||||
title: "Components/Tooltip",
|
title: "Components/Tooltip",
|
||||||
component: Tooltip,
|
component: Tooltip,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj<TooltipProps>) => (
|
(Story) => (
|
||||||
<div class="p-16">
|
<div class="p-16">
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
render: (args: TooltipProps) => (
|
render: (args) => (
|
||||||
<div class="p-16">
|
<div class="p-16">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
{...args}
|
{...args}
|
||||||
@@ -33,7 +33,7 @@ const meta: Meta<TooltipProps> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<TooltipProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
|
|
||||||
import { Family, Hierarchy, Typography, Weight } from "./Typography";
|
import { Family, Hierarchy, Typography, Weight } from "./Typography";
|
||||||
import { Component, For, Show } from "solid-js";
|
import { Component, For, Show } from "solid-js";
|
||||||
@@ -73,14 +73,14 @@ const TypographyExamples: Component<TypographyExamplesProps> = (props) => (
|
|||||||
</table>
|
</table>
|
||||||
);
|
);
|
||||||
|
|
||||||
const meta: Meta<TypographyExamplesProps> = {
|
const meta: Meta<typeof TypographyExamples> = {
|
||||||
title: "Components/Typography",
|
title: "Components/Typography",
|
||||||
component: TypographyExamples,
|
component: TypographyExamples,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<TypographyExamplesProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const BodyCondensed: Story = {
|
export const BodyCondensed: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ import { getInClasses } from "@/src/util";
|
|||||||
export type Hierarchy = "body" | "title" | "headline" | "label" | "teaser";
|
export type Hierarchy = "body" | "title" | "headline" | "label" | "teaser";
|
||||||
export type Weight = "normal" | "medium" | "bold";
|
export type Weight = "normal" | "medium" | "bold";
|
||||||
export type Family = "regular" | "mono";
|
export type Family = "regular" | "mono";
|
||||||
export type Transform = "uppercase" | "lowercase" | "capitalize";
|
type Transform = "uppercase" | "lowercase" | "capitalize";
|
||||||
export interface SizeForHierarchy {
|
interface SizeForHierarchy {
|
||||||
body: "default" | "s" | "xs" | "xxs";
|
body: "default" | "s" | "xs" | "xxs";
|
||||||
headline: "default" | "m" | "l" | "xl" | "xxl";
|
headline: "default" | "m" | "l" | "xl" | "xxl";
|
||||||
title: "default" | "m" | "l";
|
title: "default" | "m" | "l";
|
||||||
label: "default" | "s" | "xs" | "xxs";
|
label: "default" | "s" | "xs" | "xxs";
|
||||||
teaser: "default";
|
teaser: "default";
|
||||||
}
|
}
|
||||||
export interface TagForHierarchy {
|
interface TagForHierarchy {
|
||||||
body: "span" | "p" | "div";
|
body: "span" | "p" | "div";
|
||||||
headline: "h1" | "h2" | "h3" | "h4";
|
headline: "h1" | "h2" | "h3" | "h4";
|
||||||
title: "h1" | "h2" | "h3" | "h4";
|
title: "h1" | "h2" | "h3" | "h4";
|
||||||
@@ -40,7 +40,7 @@ const defaultTagMap = {
|
|||||||
label: "span",
|
label: "span",
|
||||||
teaser: "h3",
|
teaser: "h3",
|
||||||
} as const;
|
} as const;
|
||||||
export interface TypographyProps<H extends Hierarchy> {
|
interface TypographyProps<H extends Hierarchy> {
|
||||||
hierarchy: H;
|
hierarchy: H;
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
size?: SizeForHierarchy[H];
|
size?: SizeForHierarchy[H];
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createContext, JSX, useContext } from "solid-js";
|
import { createContext, JSX, useContext } from "solid-js";
|
||||||
import { ApiCall, OperationArgs, OperationNames } from "./api";
|
import { ApiCall, OperationArgs, OperationNames } from "./api";
|
||||||
|
|
||||||
export interface ApiClient {
|
interface ApiClient {
|
||||||
fetch: Fetcher;
|
fetch: Fetcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { addClanURI, setActiveClanURI } from "@/src/stores/clan";
|
|||||||
import { Params, Navigator, useParams, useSearchParams } from "@solidjs/router";
|
import { Params, Navigator, useParams, useSearchParams } from "@solidjs/router";
|
||||||
|
|
||||||
export const encodeBase64 = (value: string) => window.btoa(value);
|
export const encodeBase64 = (value: string) => window.btoa(value);
|
||||||
export const decodeBase64 = (value: string) => window.atob(value);
|
const decodeBase64 = (value: string) => window.atob(value);
|
||||||
|
|
||||||
export const selectClanFolder = async () => {
|
export const selectClanFolder = async () => {
|
||||||
const req = callApi("get_clan_folder", {});
|
const req = callApi("get_clan_folder", {});
|
||||||
@@ -80,7 +80,7 @@ export const navigateToClan = (navigate: Navigator, clanURI: string) => {
|
|||||||
export const navigateToOnboarding = (navigate: Navigator, addClan: boolean) =>
|
export const navigateToOnboarding = (navigate: Navigator, addClan: boolean) =>
|
||||||
navigate(`/${addClan ? "?addClan=true" : ""}`);
|
navigate(`/${addClan ? "?addClan=true" : ""}`);
|
||||||
|
|
||||||
export const navigateToMachine = (
|
const navigateToMachine = (
|
||||||
navigate: Navigator,
|
navigate: Navigator,
|
||||||
clanURI: string,
|
clanURI: string,
|
||||||
name: string,
|
name: string,
|
||||||
@@ -90,7 +90,7 @@ export const navigateToMachine = (
|
|||||||
navigate(path);
|
navigate(path);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const clanURIParam = (params: Params) => {
|
const clanURIParam = (params: Params) => {
|
||||||
try {
|
try {
|
||||||
return decodeBase64(params.clanURI);
|
return decodeBase64(params.clanURI);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -101,19 +101,19 @@ export const clanURIParam = (params: Params) => {
|
|||||||
|
|
||||||
export const useClanURI = () => clanURIParam(useParams());
|
export const useClanURI = () => clanURIParam(useParams());
|
||||||
|
|
||||||
export const machineNameParam = (params: Params) => {
|
const machineNameParam = (params: Params) => {
|
||||||
return params.machineName;
|
return params.machineName;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const inputParam = (params: Params) => params.input;
|
const inputParam = (params: Params) => params.input;
|
||||||
export const nameParam = (params: Params) => params.name;
|
const nameParam = (params: Params) => params.name;
|
||||||
export const idParam = (params: Params) => params.id;
|
const idParam = (params: Params) => params.id;
|
||||||
|
|
||||||
export const useMachineName = (): string => machineNameParam(useParams());
|
export const useMachineName = (): string => machineNameParam(useParams());
|
||||||
export const useInputParam = (): string => inputParam(useParams());
|
const useInputParam = (): string => inputParam(useParams());
|
||||||
export const useNameParam = (): string => nameParam(useParams());
|
const useNameParam = (): string => nameParam(useParams());
|
||||||
|
|
||||||
export const maybeUseIdParam = (): string | null => {
|
const maybeUseIdParam = (): string | null => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
if (params.id === undefined) {
|
if (params.id === undefined) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import { useMutation, useQueryClient } from "@tanstack/solid-query";
|
|
||||||
import { callApi, OperationArgs } from "@/src/hooks/api";
|
|
||||||
import { encodeBase64 } from "@/src/hooks/clan";
|
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
export const updateMachine = useMutation(() => ({
|
|
||||||
mutationFn: async (args: OperationArgs<"set_machine">) => {
|
|
||||||
const call = callApi("set_machine", args);
|
|
||||||
return {
|
|
||||||
args,
|
|
||||||
...call,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
onSuccess: async ({ args }) => {
|
|
||||||
const {
|
|
||||||
name,
|
|
||||||
flake: { identifier },
|
|
||||||
} = args.machine;
|
|
||||||
|
|
||||||
await queryClient.invalidateQueries({
|
|
||||||
queryKey: ["clans", encodeBase64(identifier), "machine", name],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
@@ -44,7 +44,7 @@ window.notifyBus = (msg: ProcessMessage) => {
|
|||||||
*
|
*
|
||||||
* consider using useNotify for reactive usage on solidjs
|
* consider using useNotify for reactive usage on solidjs
|
||||||
*/
|
*/
|
||||||
export function _subscribeNotify<T extends ProcessMessage>(
|
function _subscribeNotify<T extends ProcessMessage>(
|
||||||
filter: (msg: T) => boolean,
|
filter: (msg: T) => boolean,
|
||||||
callback: (msg: T) => void,
|
callback: (msg: T) => void,
|
||||||
) {
|
) {
|
||||||
@@ -65,7 +65,7 @@ export function _subscribeNotify<T extends ProcessMessage>(
|
|||||||
* The signal has the value of the last message where filter was true
|
* The signal has the value of the last message where filter was true
|
||||||
* null in case no message was recieved yet
|
* null in case no message was recieved yet
|
||||||
*/
|
*/
|
||||||
export function useNotify<T extends ProcessMessage = ProcessMessage>(
|
function useNotify<T extends ProcessMessage = ProcessMessage>(
|
||||||
filter: (msg: T) => boolean = () => true as boolean,
|
filter: (msg: T) => boolean = () => true as boolean,
|
||||||
) {
|
) {
|
||||||
const [message, setMessage] = createSignal<T | null>(null);
|
const [message, setMessage] = createSignal<T | null>(null);
|
||||||
|
|||||||
@@ -16,16 +16,16 @@ export interface ClanDetails {
|
|||||||
fieldsSchema: SuccessData<"get_clan_details_schema">;
|
fieldsSchema: SuccessData<"get_clan_details_schema">;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Tags = SuccessData<"list_tags">;
|
type Tags = SuccessData<"list_tags">;
|
||||||
export type Machine = SuccessData<"get_machine">;
|
export type Machine = SuccessData<"get_machine">;
|
||||||
|
|
||||||
export type MachineState = SuccessData<"get_machine_state">;
|
type MachineState = SuccessData<"get_machine_state">;
|
||||||
export type MachineStatus = MachineState["status"];
|
export type MachineStatus = MachineState["status"];
|
||||||
|
|
||||||
export type ListMachines = SuccessData<"list_machines">;
|
type ListMachines = SuccessData<"list_machines">;
|
||||||
export type MachineDetails = SuccessData<"get_machine_details">;
|
type MachineDetails = SuccessData<"get_machine_details">;
|
||||||
|
|
||||||
export type ListServiceModules = SuccessData<"list_service_modules">;
|
type ListServiceModules = SuccessData<"list_service_modules">;
|
||||||
export type ListServiceInstances = SuccessData<"list_service_instances">;
|
export type ListServiceInstances = SuccessData<"list_service_instances">;
|
||||||
|
|
||||||
export interface MachineDetail {
|
export interface MachineDetail {
|
||||||
@@ -35,7 +35,7 @@ export interface MachineDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type MachinesQueryResult = UseQueryResult<ListMachines>;
|
export type MachinesQueryResult = UseQueryResult<ListMachines>;
|
||||||
export type ClanListQueryResult = UseQueryResult<ClanDetails>[];
|
type ClanListQueryResult = UseQueryResult<ClanDetails>[];
|
||||||
|
|
||||||
export const DefaultQueryClient = new QueryClient({
|
export const DefaultQueryClient = new QueryClient({
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
@@ -67,7 +67,7 @@ export const useMachinesQuery = (clanURI: string) => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const machineKey = (clanUri: string, machineName: string) => [
|
const machineKey = (clanUri: string, machineName: string) => [
|
||||||
...clanKey(clanUri),
|
...clanKey(clanUri),
|
||||||
"machine",
|
"machine",
|
||||||
encodeBase64(machineName),
|
encodeBase64(machineName),
|
||||||
@@ -174,7 +174,7 @@ export const useMachineStateQuery = (clanURI: string, machineName: string) => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useServiceModulesQuery = (clanURI: string) => {
|
const useServiceModulesQuery = (clanURI: string) => {
|
||||||
const client = useApiClient();
|
const client = useApiClient();
|
||||||
|
|
||||||
return useQuery<ListServiceModules>(() => ({
|
return useQuery<ListServiceModules>(() => ({
|
||||||
@@ -222,10 +222,7 @@ export const useServiceInstancesQuery = (clanURI: string) => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useMachineDetailsQuery = (
|
const useMachineDetailsQuery = (clanURI: string, machineName: string) => {
|
||||||
clanURI: string,
|
|
||||||
machineName: string,
|
|
||||||
) => {
|
|
||||||
const client = useApiClient();
|
const client = useApiClient();
|
||||||
return useQuery<MachineDetails>(() => ({
|
return useQuery<MachineDetails>(() => ({
|
||||||
queryKey: [machineKey(clanURI, machineName), "details"],
|
queryKey: [machineKey(clanURI, machineName), "details"],
|
||||||
@@ -251,7 +248,7 @@ export const useMachineDetailsQuery = (
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ClanDetailsPersister = experimental_createQueryPersister({
|
const ClanDetailsPersister = experimental_createQueryPersister({
|
||||||
storage: ClanDetailsStore,
|
storage: ClanDetailsStore,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -373,10 +370,10 @@ export const useClanListQuery = (
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MachineFlashOptions = SuccessData<"get_machine_flash_options">;
|
type MachineFlashOptions = SuccessData<"get_machine_flash_options">;
|
||||||
export type MachineFlashOptionsQuery = UseQueryResult<MachineFlashOptions>;
|
type MachineFlashOptionsQuery = UseQueryResult<MachineFlashOptions>;
|
||||||
|
|
||||||
export const useMachineFlashOptions = (): MachineFlashOptionsQuery => {
|
const useMachineFlashOptions = (): MachineFlashOptionsQuery => {
|
||||||
const client = useApiClient();
|
const client = useApiClient();
|
||||||
return useQuery<MachineFlashOptions>(() => ({
|
return useQuery<MachineFlashOptions>(() => ({
|
||||||
queryKey: ["flash_options"],
|
queryKey: ["flash_options"],
|
||||||
@@ -395,8 +392,8 @@ export const useMachineFlashOptions = (): MachineFlashOptionsQuery => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SystemStorageOptions = SuccessData<"list_system_storage_devices">;
|
type SystemStorageOptions = SuccessData<"list_system_storage_devices">;
|
||||||
export type SystemStorageOptionsQuery = UseQueryResult<SystemStorageOptions>;
|
type SystemStorageOptionsQuery = UseQueryResult<SystemStorageOptions>;
|
||||||
|
|
||||||
export const useSystemStorageOptions = (): SystemStorageOptionsQuery => {
|
export const useSystemStorageOptions = (): SystemStorageOptionsQuery => {
|
||||||
const client = useApiClient();
|
const client = useApiClient();
|
||||||
@@ -417,10 +414,8 @@ export const useSystemStorageOptions = (): SystemStorageOptionsQuery => {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MachineHardwareSummary =
|
type MachineHardwareSummary = SuccessData<"get_machine_hardware_summary">;
|
||||||
SuccessData<"get_machine_hardware_summary">;
|
type MachineHardwareSummaryQuery = UseQueryResult<MachineHardwareSummary>;
|
||||||
export type MachineHardwareSummaryQuery =
|
|
||||||
UseQueryResult<MachineHardwareSummary>;
|
|
||||||
|
|
||||||
export const useMachineHardwareSummary = (
|
export const useMachineHardwareSummary = (
|
||||||
clanUri: string,
|
clanUri: string,
|
||||||
@@ -457,8 +452,8 @@ export const useMachineHardwareSummary = (
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MachineDiskSchema = SuccessData<"get_machine_disk_schemas">;
|
type MachineDiskSchema = SuccessData<"get_machine_disk_schemas">;
|
||||||
export type MachineDiskSchemaQuery = UseQueryResult<MachineDiskSchema>;
|
type MachineDiskSchemaQuery = UseQueryResult<MachineDiskSchema>;
|
||||||
|
|
||||||
export const useMachineDiskSchemas = (
|
export const useMachineDiskSchemas = (
|
||||||
clanUri: string,
|
clanUri: string,
|
||||||
@@ -496,7 +491,7 @@ export const useMachineDiskSchemas = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type MachineGenerators = SuccessData<"get_generators">;
|
export type MachineGenerators = SuccessData<"get_generators">;
|
||||||
export type MachineGeneratorsQuery = UseQueryResult<MachineGenerators>;
|
type MachineGeneratorsQuery = UseQueryResult<MachineGenerators>;
|
||||||
|
|
||||||
export const useMachineGenerators = (
|
export const useMachineGenerators = (
|
||||||
clanUri: string,
|
clanUri: string,
|
||||||
@@ -538,7 +533,7 @@ export const useMachineGenerators = (
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ServiceModulesQuery = ReturnType<typeof useServiceModules>;
|
type ServiceModulesQuery = ReturnType<typeof useServiceModules>;
|
||||||
export type ServiceModules = SuccessData<"list_service_modules">;
|
export type ServiceModules = SuccessData<"list_service_modules">;
|
||||||
export const useServiceModules = (clanUri: string) => {
|
export const useServiceModules = (clanUri: string) => {
|
||||||
const client = useApiClient();
|
const client = useApiClient();
|
||||||
@@ -566,7 +561,7 @@ export const useServiceModules = (clanUri: string) => {
|
|||||||
export const clanKey = (clanUri: string) => ["clans", encodeBase64(clanUri)];
|
export const clanKey = (clanUri: string) => ["clans", encodeBase64(clanUri)];
|
||||||
|
|
||||||
export type ServiceInstancesQuery = ReturnType<typeof useServiceInstances>;
|
export type ServiceInstancesQuery = ReturnType<typeof useServiceInstances>;
|
||||||
export type ServiceInstances = SuccessData<"list_service_instances">;
|
type ServiceInstances = SuccessData<"list_service_instances">;
|
||||||
export const useServiceInstances = (clanUri: string) => {
|
export const useServiceInstances = (clanUri: string) => {
|
||||||
const client = useApiClient();
|
const client = useApiClient();
|
||||||
return useQuery(() => ({
|
return useQuery(() => ({
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import {
|
|||||||
} from "solid-js";
|
} from "solid-js";
|
||||||
import { createStore, SetStoreFunction, Store } from "solid-js/store";
|
import { createStore, SetStoreFunction, Store } from "solid-js/store";
|
||||||
|
|
||||||
export interface StepBase {
|
interface StepBase {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Step<ExtraFields = unknown> = StepBase & ExtraFields;
|
type Step<ExtraFields = unknown> = StepBase & ExtraFields;
|
||||||
|
|
||||||
export interface StepOptions<Id, StoreType> {
|
interface StepOptions<Id, StoreType> {
|
||||||
initialStep: Id;
|
initialStep: Id;
|
||||||
initialStoreData?: StoreType;
|
initialStoreData?: StoreType;
|
||||||
}
|
}
|
||||||
@@ -95,10 +95,7 @@ export function createStepper<
|
|||||||
}
|
}
|
||||||
|
|
||||||
type StoreTuple<T> = [get: Store<T>, set: SetStoreFunction<T>];
|
type StoreTuple<T> = [get: Store<T>, set: SetStoreFunction<T>];
|
||||||
export interface StepperReturn<
|
interface StepperReturn<T extends readonly Step[], StepId = T[number]["id"]> {
|
||||||
T extends readonly Step[],
|
|
||||||
StepId = T[number]["id"],
|
|
||||||
> {
|
|
||||||
_store: never;
|
_store: never;
|
||||||
activeStep: Accessor<StepId>;
|
activeStep: Accessor<StepId>;
|
||||||
setActiveStep: (id: StepId) => void;
|
setActiveStep: (id: StepId) => void;
|
||||||
|
|||||||
@@ -1,45 +1,43 @@
|
|||||||
import { fn } from "storybook/test";
|
import { fn } from "storybook/test";
|
||||||
import type { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { ClanSettingsModal, ClanSettingsModalProps } from "./ClanSettingsModal";
|
import { ClanSettingsModal } from "./ClanSettingsModal";
|
||||||
|
|
||||||
const meta: Meta<ClanSettingsModalProps> = {
|
const meta: Meta<typeof ClanSettingsModal> = {
|
||||||
title: "Modals/ClanSettings",
|
title: "Modals/ClanSettings",
|
||||||
component: ClanSettingsModal,
|
component: ClanSettingsModal,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<ClanSettingsModalProps>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
const props: ClanSettingsModalProps = {
|
export const Default: Story = {
|
||||||
onClose: fn(),
|
args: {
|
||||||
model: {
|
onClose: fn(),
|
||||||
uri: "/home/foo/my-clan",
|
model: {
|
||||||
details: {
|
uri: "/home/foo/my-clan",
|
||||||
name: "Sol",
|
details: {
|
||||||
description: null,
|
name: "Sol",
|
||||||
icon: null,
|
description: null,
|
||||||
},
|
icon: null,
|
||||||
fieldsSchema: {
|
|
||||||
name: {
|
|
||||||
readonly: true,
|
|
||||||
reason: null,
|
|
||||||
readonly_members: [],
|
|
||||||
},
|
},
|
||||||
description: {
|
fieldsSchema: {
|
||||||
readonly: false,
|
name: {
|
||||||
reason: null,
|
readonly: true,
|
||||||
readonly_members: [],
|
reason: null,
|
||||||
},
|
readonly_members: [],
|
||||||
icon: {
|
},
|
||||||
readonly: false,
|
description: {
|
||||||
reason: null,
|
readonly: false,
|
||||||
readonly_members: [],
|
reason: null,
|
||||||
|
readonly_members: [],
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
readonly: false,
|
||||||
|
reason: null,
|
||||||
|
readonly_members: [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Default: Story = {
|
|
||||||
args: props,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { useClanListQuery } from "@/src/hooks/queries";
|
|||||||
import { Alert } from "@/src/components/Alert/Alert";
|
import { Alert } from "@/src/components/Alert/Alert";
|
||||||
import { NavSection } from "@/src/components/NavSection/NavSection";
|
import { NavSection } from "@/src/components/NavSection/NavSection";
|
||||||
|
|
||||||
export interface ListClansModalProps {
|
interface ListClansModalProps {
|
||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
error?: {
|
error?: {
|
||||||
title: string;
|
title: string;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import { ListClansModal } from "@/src/modals/ListClansModal/ListClansModal";
|
|||||||
import { AddMachine } from "@/src/workflows/AddMachine/AddMachine";
|
import { AddMachine } from "@/src/workflows/AddMachine/AddMachine";
|
||||||
import { SelectService } from "@/src/workflows/Service/SelectServiceFlyout";
|
import { SelectService } from "@/src/workflows/Service/SelectServiceFlyout";
|
||||||
|
|
||||||
export type WorldMode = "default" | "select" | "service" | "create" | "move";
|
type WorldMode = "default" | "select" | "service" | "create" | "move";
|
||||||
|
|
||||||
function createClanContext(
|
function createClanContext(
|
||||||
clanURI: string,
|
clanURI: string,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type FieldNames = "name" | "description" | "machineClass";
|
|||||||
|
|
||||||
type FormValues = v.InferInput<typeof schema>;
|
type FormValues = v.InferInput<typeof schema>;
|
||||||
|
|
||||||
export interface SectionGeneralProps {
|
interface SectionGeneralProps {
|
||||||
clanURI: string;
|
clanURI: string;
|
||||||
machineName: string;
|
machineName: string;
|
||||||
onSubmit: (values: FormValues) => Promise<void>;
|
onSubmit: (values: FormValues) => Promise<void>;
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ export function createMachineMesh() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCubeBase(
|
function createCubeBase(
|
||||||
color: THREE.ColorRepresentation,
|
color: THREE.ColorRepresentation,
|
||||||
emissive: THREE.ColorRepresentation,
|
emissive: THREE.ColorRepresentation,
|
||||||
geometry: THREE.BoxGeometry,
|
geometry: THREE.BoxGeometry,
|
||||||
@@ -70,7 +70,7 @@ export function createCubeBase(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Function to build rounded rect shape
|
// Function to build rounded rect shape
|
||||||
export function roundedRectShape(w: number, h: number, r: number) {
|
function roundedRectShape(w: number, h: number, r: number) {
|
||||||
const shape = new THREE.Shape();
|
const shape = new THREE.Shape();
|
||||||
const x = -w / 2;
|
const x = -w / 2;
|
||||||
const y = -h / 2;
|
const y = -h / 2;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const [lastClickedMachine, setLastClickedMachine] = createSignal<string | null>(
|
|||||||
|
|
||||||
// Exported so others could also emit the signal if needed
|
// Exported so others could also emit the signal if needed
|
||||||
// And for testing purposes
|
// And for testing purposes
|
||||||
export function emitMachineClick(id: string | null) {
|
function emitMachineClick(id: string | null) {
|
||||||
setLastClickedMachine(id);
|
setLastClickedMachine(id);
|
||||||
if (id) {
|
if (id) {
|
||||||
// Clear after a short delay to allow re-clicking the same machine
|
// Clear after a short delay to allow re-clicking the same machine
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const [highlightGroups, setHighlightGroups] = createStore<
|
|||||||
>({});
|
>({});
|
||||||
|
|
||||||
// Add highlight
|
// Add highlight
|
||||||
export function highlight(group: string, nodeId: string) {
|
function highlight(group: string, nodeId: string) {
|
||||||
setHighlightGroups(group, (prev = new Set()) => {
|
setHighlightGroups(group, (prev = new Set()) => {
|
||||||
const next = new Set(prev);
|
const next = new Set(prev);
|
||||||
next.add(nodeId);
|
next.add(nodeId);
|
||||||
@@ -16,7 +16,7 @@ export function highlight(group: string, nodeId: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove highlight
|
// Remove highlight
|
||||||
export function unhighlight(group: string, nodeId: string) {
|
function unhighlight(group: string, nodeId: string) {
|
||||||
setHighlightGroups(group, (prev = new Set()) => {
|
setHighlightGroups(group, (prev = new Set()) => {
|
||||||
const next = new Set(prev);
|
const next = new Set(prev);
|
||||||
next.delete(nodeId);
|
next.delete(nodeId);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Meta, StoryObj } from "@kachurun/storybook-solid";
|
import { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { Splash } from "./splash";
|
import { Splash } from "./splash";
|
||||||
|
|
||||||
const meta: Meta = {
|
const meta: Meta = {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { makePersisted } from "@solid-primitives/storage";
|
|||||||
|
|
||||||
export type SceneData = Record<string, { position: [number, number] }>;
|
export type SceneData = Record<string, { position: [number, number] }>;
|
||||||
|
|
||||||
export interface ClanStoreType {
|
interface ClanStoreType {
|
||||||
clanURIs: string[];
|
clanURIs: string[];
|
||||||
activeClanURI?: string;
|
activeClanURI?: string;
|
||||||
sceneData: Record<string, SceneData>;
|
sceneData: Record<string, SceneData>;
|
||||||
|
|||||||
90
pkgs/clan-app/ui/src/types/index.d.ts
vendored
90
pkgs/clan-app/ui/src/types/index.d.ts
vendored
@@ -1,90 +0,0 @@
|
|||||||
// @ts-nocheck
|
|
||||||
declare module "@kachurun/storybook-solid" {
|
|
||||||
import type { SolidRenderer } from "types";
|
|
||||||
import type {
|
|
||||||
AnnotatedStoryFn,
|
|
||||||
Args,
|
|
||||||
ArgsFromMeta,
|
|
||||||
ArgsStoryFn,
|
|
||||||
ComponentAnnotations,
|
|
||||||
DecoratorFunction,
|
|
||||||
LoaderFunction,
|
|
||||||
ProjectAnnotations,
|
|
||||||
StoryAnnotations,
|
|
||||||
StoryContext as GenericStoryContext,
|
|
||||||
StrictArgs,
|
|
||||||
} from "@storybook/types";
|
|
||||||
import type { Component as ComponentType, ComponentProps } from "solid-js";
|
|
||||||
import type { SetOptional, Simplify } from "type-fest";
|
|
||||||
export type {
|
|
||||||
ArgTypes,
|
|
||||||
Args,
|
|
||||||
Parameters,
|
|
||||||
StrictArgs,
|
|
||||||
} from "@storybook/types";
|
|
||||||
export type { SolidRenderer };
|
|
||||||
/**
|
|
||||||
* Metadata to configure the stories for a component.
|
|
||||||
*
|
|
||||||
* @see [Default export](https://storybook.js.org/docs/formats/component-story-format/#default-export)
|
|
||||||
*/
|
|
||||||
export type Meta<TCmpOrArgs = Args> =
|
|
||||||
TCmpOrArgs extends ComponentType<any>
|
|
||||||
? ComponentAnnotations<SolidRenderer, ComponentProps<TCmpOrArgs>>
|
|
||||||
: ComponentAnnotations<SolidRenderer, TCmpOrArgs>;
|
|
||||||
/**
|
|
||||||
* Story function that represents a CSFv2 component example.
|
|
||||||
*
|
|
||||||
* @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports)
|
|
||||||
*/
|
|
||||||
export type StoryFn<TCmpOrArgs = Args> =
|
|
||||||
TCmpOrArgs extends ComponentType<any>
|
|
||||||
? AnnotatedStoryFn<SolidRenderer, ComponentProps<TCmpOrArgs>>
|
|
||||||
: AnnotatedStoryFn<SolidRenderer, TCmpOrArgs>;
|
|
||||||
/**
|
|
||||||
* Story function that represents a CSFv3 component example.
|
|
||||||
*
|
|
||||||
* @see [Named Story exports](https://storybook.js.org/docs/formats/component-story-format/#named-story-exports)
|
|
||||||
*/
|
|
||||||
export type StoryObj<TMetaOrCmpOrArgs = Args> = TMetaOrCmpOrArgs extends {
|
|
||||||
render?: ArgsStoryFn<SolidRenderer, any>;
|
|
||||||
component?: infer Component;
|
|
||||||
args?: infer DefaultArgs;
|
|
||||||
}
|
|
||||||
? Simplify<
|
|
||||||
(Component extends ComponentType<any>
|
|
||||||
? ComponentProps<Component>
|
|
||||||
: unknown) &
|
|
||||||
ArgsFromMeta<SolidRenderer, TMetaOrCmpOrArgs>
|
|
||||||
> extends infer TArgs
|
|
||||||
? StoryAnnotations<
|
|
||||||
SolidRenderer,
|
|
||||||
TArgs,
|
|
||||||
SetOptional<
|
|
||||||
TArgs,
|
|
||||||
keyof TArgs & keyof (DefaultArgs & ActionArgs<TArgs>)
|
|
||||||
>
|
|
||||||
>
|
|
||||||
: never
|
|
||||||
: TMetaOrCmpOrArgs extends ComponentType<any>
|
|
||||||
? StoryAnnotations<SolidRenderer, ComponentProps<TMetaOrCmpOrArgs>>
|
|
||||||
: StoryAnnotations<SolidRenderer, TMetaOrCmpOrArgs>;
|
|
||||||
type ActionArgs<TArgs> = {
|
|
||||||
[P in keyof TArgs as TArgs[P] extends (...args: any[]) => any
|
|
||||||
? ((...args: any[]) => void) extends TArgs[P]
|
|
||||||
? P
|
|
||||||
: never
|
|
||||||
: never]: TArgs[P];
|
|
||||||
};
|
|
||||||
export type Decorator<TArgs = StrictArgs> = DecoratorFunction<
|
|
||||||
SolidRenderer,
|
|
||||||
TArgs
|
|
||||||
>;
|
|
||||||
export type Loader<TArgs = StrictArgs> = LoaderFunction<SolidRenderer, TArgs>;
|
|
||||||
export type StoryContext<TArgs = StrictArgs> = GenericStoryContext<
|
|
||||||
SolidRenderer,
|
|
||||||
TArgs
|
|
||||||
>;
|
|
||||||
export type Preview = ProjectAnnotations<SolidRenderer>;
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=index.d.ts.map
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { AddMachine } from "@/src/workflows/AddMachine/AddMachine";
|
import { AddMachine } from "@/src/workflows/AddMachine/AddMachine";
|
||||||
import {
|
import {
|
||||||
createMemoryHistory,
|
createMemoryHistory,
|
||||||
@@ -62,7 +62,7 @@ const meta: Meta<typeof AddMachine> = {
|
|||||||
title: "workflows/add-machine",
|
title: "workflows/add-machine",
|
||||||
component: AddMachine,
|
component: AddMachine,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext) => {
|
(Story) => {
|
||||||
const Routes: RouteDefinition[] = [
|
const Routes: RouteDefinition[] = [
|
||||||
{
|
{
|
||||||
path: "/clans/:clanURI",
|
path: "/clans/:clanURI",
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const AddMachineStepper = (props: AddMachineStepperProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface AddMachineProps {
|
interface AddMachineProps {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onCreated: (id: string) => void;
|
onCreated: (id: string) => void;
|
||||||
initialStep?: AddMachineSteps[number]["id"];
|
initialStep?: AddMachineSteps[number]["id"];
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Typography } from "@/src/components/Typography/Typography";
|
|||||||
import { Show } from "solid-js";
|
import { Show } from "solid-js";
|
||||||
import { Alert } from "@/src/components/Alert/Alert";
|
import { Alert } from "@/src/components/Alert/Alert";
|
||||||
|
|
||||||
export interface StepProgressProps {
|
interface StepProgressProps {
|
||||||
onDone: () => void;
|
onDone: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import { InstallModal } from "./InstallMachine";
|
import { InstallModal } from "./InstallMachine";
|
||||||
import {
|
import {
|
||||||
createMemoryHistory,
|
createMemoryHistory,
|
||||||
@@ -161,7 +161,7 @@ const meta: Meta<typeof InstallModal> = {
|
|||||||
title: "workflows/install",
|
title: "workflows/install",
|
||||||
component: InstallModal,
|
component: InstallModal,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext) => {
|
(Story) => {
|
||||||
const Routes: RouteDefinition[] = [
|
const Routes: RouteDefinition[] = [
|
||||||
{
|
{
|
||||||
path: "/clans/:clanURI",
|
path: "/clans/:clanURI",
|
||||||
@@ -198,10 +198,9 @@ const meta: Meta<typeof InstallModal> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
|
|
||||||
type Story = StoryObj<typeof InstallModal>;
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
export const Init: Story = {
|
export const Init: Story = {
|
||||||
description: "Welcome step for the installation workflow",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -209,7 +208,6 @@ export const Init: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const CreateInstallerProse: Story = {
|
export const CreateInstallerProse: Story = {
|
||||||
description: "Prose step for creating an installer",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -217,7 +215,6 @@ export const CreateInstallerProse: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const CreateInstallerImage: Story = {
|
export const CreateInstallerImage: Story = {
|
||||||
description: "Configure the image to install",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -225,7 +222,6 @@ export const CreateInstallerImage: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const CreateInstallerDisk: Story = {
|
export const CreateInstallerDisk: Story = {
|
||||||
description: "Select a disk to install the image on",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -233,7 +229,6 @@ export const CreateInstallerDisk: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const CreateInstallerProgress: Story = {
|
export const CreateInstallerProgress: Story = {
|
||||||
description: "Showed while the USB stick is being flashed",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -241,7 +236,6 @@ export const CreateInstallerProgress: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const CreateInstallerDone: Story = {
|
export const CreateInstallerDone: Story = {
|
||||||
description: "Installation done step",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -249,7 +243,6 @@ export const CreateInstallerDone: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const InstallConfigureAddress: Story = {
|
export const InstallConfigureAddress: Story = {
|
||||||
description: "Installation configure address step",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -257,7 +250,6 @@ export const InstallConfigureAddress: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const InstallCheckHardware: Story = {
|
export const InstallCheckHardware: Story = {
|
||||||
description: "Installation check hardware step",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -265,7 +257,6 @@ export const InstallCheckHardware: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const InstallSelectDisk: Story = {
|
export const InstallSelectDisk: Story = {
|
||||||
description: "Select disk to install the system on",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -273,7 +264,6 @@ export const InstallSelectDisk: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const InstallVars: Story = {
|
export const InstallVars: Story = {
|
||||||
description: "Fill required credentials and data for the installation",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -281,7 +271,6 @@ export const InstallVars: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const InstallSummary: Story = {
|
export const InstallSummary: Story = {
|
||||||
description: "Summary of the installation steps",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -289,7 +278,6 @@ export const InstallSummary: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const InstallProgress: Story = {
|
export const InstallProgress: Story = {
|
||||||
description: "Shown while the installation is in progress",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
@@ -297,7 +285,6 @@ export const InstallProgress: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const InstallDone: Story = {
|
export const InstallDone: Story = {
|
||||||
description: "Shown after the installation is done",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Test Machine",
|
machineName: "Test Machine",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const InstallStepper = (props: InstallStepperProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface InstallModalProps {
|
interface InstallModalProps {
|
||||||
machineName: string;
|
machineName: string;
|
||||||
initialStep?: InstallSteps[number]["id"];
|
initialStep?: InstallSteps[number]["id"];
|
||||||
mount?: Node;
|
mount?: Node;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid";
|
import type { Meta, StoryObj } from "storybook-solidjs-vite";
|
||||||
import {
|
import {
|
||||||
createMemoryHistory,
|
createMemoryHistory,
|
||||||
MemoryRouter,
|
MemoryRouter,
|
||||||
@@ -134,7 +134,7 @@ const meta: Meta<typeof UpdateModal> = {
|
|||||||
title: "workflows/update",
|
title: "workflows/update",
|
||||||
component: UpdateModal,
|
component: UpdateModal,
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story: StoryObj, context: StoryContext) => {
|
(Story) => {
|
||||||
const Routes: RouteDefinition[] = [
|
const Routes: RouteDefinition[] = [
|
||||||
{
|
{
|
||||||
path: "/clans/:clanURI",
|
path: "/clans/:clanURI",
|
||||||
@@ -174,14 +174,12 @@ export default meta;
|
|||||||
type Story = StoryObj<typeof UpdateModal>;
|
type Story = StoryObj<typeof UpdateModal>;
|
||||||
|
|
||||||
export const Init: Story = {
|
export const Init: Story = {
|
||||||
description: "Welcome step for the update workflow",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Jon",
|
machineName: "Jon",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const Address: Story = {
|
export const Address: Story = {
|
||||||
description: "Welcome step for the update workflow",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Jon",
|
machineName: "Jon",
|
||||||
@@ -189,7 +187,6 @@ export const Address: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
export const UpdateProgress: Story = {
|
export const UpdateProgress: Story = {
|
||||||
description: "Welcome step for the update workflow",
|
|
||||||
args: {
|
args: {
|
||||||
open: true,
|
open: true,
|
||||||
machineName: "Jon",
|
machineName: "Jon",
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ const UpdateStepper = (props: UpdateStepperProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface UpdateModalProps {
|
interface UpdateModalProps {
|
||||||
machineName: string;
|
machineName: string;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
initialStep?: UpdateSteps[number]["id"];
|
initialStep?: UpdateSteps[number]["id"];
|
||||||
@@ -92,7 +92,7 @@ export interface UpdateModalProps {
|
|||||||
onClose?: () => void;
|
onClose?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const UpdateHeader = (props: { machineName: string }) => {
|
const UpdateHeader = (props: { machineName: string }) => {
|
||||||
return (
|
return (
|
||||||
<Typography hierarchy="label" size="default">
|
<Typography hierarchy="label" size="default">
|
||||||
Update: {props.machineName}
|
Update: {props.machineName}
|
||||||
@@ -206,8 +206,8 @@ const steps = [
|
|||||||
},
|
},
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
export type UpdateSteps = typeof steps;
|
type UpdateSteps = typeof steps;
|
||||||
export type PromptValues = Record<string, Record<string, string>>;
|
type PromptValues = Record<string, Record<string, string>>;
|
||||||
|
|
||||||
export const UpdateModal = (props: UpdateModalProps) => {
|
export const UpdateModal = (props: UpdateModalProps) => {
|
||||||
const stepper = createStepper(
|
const stepper = createStepper(
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import { Loader } from "@/src/components/Loader/Loader";
|
|||||||
import { Button as KButton } from "@kobalte/core/button";
|
import { Button as KButton } from "@kobalte/core/button";
|
||||||
import usbLogo from "@/logos/usb-stick-min.png?url";
|
import usbLogo from "@/logos/usb-stick-min.png?url";
|
||||||
|
|
||||||
export const InstallHeader = (props: { machineName: string }) => {
|
const InstallHeader = (props: { machineName: string }) => {
|
||||||
return (
|
return (
|
||||||
<Typography hierarchy="label" size="default">
|
<Typography hierarchy="label" size="default">
|
||||||
Installing: {props.machineName}
|
Installing: {props.machineName}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user