@kahitsan/ksui 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,14 @@
1
1
  # @kahitsan/ksui
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@kahitsan/ksui.svg)](https://www.npmjs.com/package/@kahitsan/ksui)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@kahitsan/ksui.svg)](https://www.npmjs.com/package/@kahitsan/ksui)
5
+ [![license](https://img.shields.io/npm/l/@kahitsan/ksui.svg)](./LICENSE)
6
+
3
7
  A set of UI components for SolidJS apps, built and used by the KahitSan team.
4
8
 
9
+ On npm: [@kahitsan/ksui](https://www.npmjs.com/package/@kahitsan/ksui). Docs:
10
+ [ksui.kahitsan.com](https://ksui.kahitsan.com/).
11
+
5
12
  ## What this is
6
13
 
7
14
  `@kahitsan/ksui` is a small library of ready-made user interface pieces for
@@ -15,7 +22,7 @@ the docs (see below), so this README stays short on purpose.
15
22
 
16
23
  ## Where you can use it
17
24
 
18
- There are two ways to use ksui.
25
+ There are two ways to use KSUI.
19
26
 
20
27
  1. **In your own SolidJS project.** Install it from npm and use the components
21
28
  like any other dependency. It is MIT licensed, so you are free to use it in
@@ -46,7 +53,7 @@ We do not list every component here on purpose, so this README does not fall out
46
53
  of date as the set grows. The complete, current catalog, with a live example and
47
54
  the props for each one, is in the docs:
48
55
 
49
- **https://kahitsan.github.io/ksui/**
56
+ **https://ksui.kahitsan.com/**
50
57
 
51
58
  ## Install
52
59
 
@@ -114,7 +121,7 @@ to mock the host kit and stub those calls so you can see every component render.
114
121
  The full documentation site, with a component-by-component guide and setup steps,
115
122
  will be at:
116
123
 
117
- https://kahitsan.github.io/ksui/
124
+ https://ksui.kahitsan.com/
118
125
 
119
126
  ## Contributing
120
127
 
@@ -123,6 +130,11 @@ up the repo, the code style we follow, and how to send a change.
123
130
 
124
131
  ## License
125
132
 
126
- MIT. See [LICENSE](./LICENSE). You are free to use ksui in your own personal or
133
+ MIT. See [LICENSE](./LICENSE). You are free to use KSUI in your own personal or
127
134
  commercial SolidJS projects, as long as you keep the MIT license notice. Source
128
135
  lives at https://github.com/KahitSan/ksui.
136
+
137
+ ---
138
+
139
+ Created with ♥ by [Luis Edward Miranda](https://github.com/llupRisinglll) for
140
+ KahitSan Corp.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kahitsan/ksui",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "ksui is a set of shared SolidJS UI components plus the @kserp/host-ui type contract for KahitSan/Hilinga plugins. Published to the public npm registry and consumed as a normal dependency. Ships source under a `solid` export condition so the consumer's vite-plugin-solid compiles it with solid-js + @kserp/host-ui externalized to the host runtime.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -0,0 +1,84 @@
1
+ // DateTile — a compact calendar day cell.
2
+ //
3
+ // A 60x68 tile with three stacked parts: a small top band (e.g. a month
4
+ // label), a big primary value (e.g. the day-of-month), and an optional
5
+ // muted sub-label (e.g. hours worked, a count, a short note). It is the
6
+ // visual unit a caller repeats into a ledger-style row of days — scanned
7
+ // like a register, not rendered as a full month grid.
8
+ //
9
+ // Domain-free by design: it knows nothing about timesheets, payroll, or any
10
+ // data shape. The caller formats every string it shows (`topLabel`,
11
+ // `value`, `subLabel`) and owns selection state. Pass `onToggle` to make the
12
+ // tile an interactive, selectable button (with `aria-pressed`); omit it for a
13
+ // static, read-only cell that renders dimmed so a row can show which tiles are
14
+ // "in" vs "out" of a selection at a glance.
15
+
16
+ import { Show, type JSX } from "solid-js";
17
+ import { Dynamic } from "solid-js/web";
18
+
19
+ export interface DateTileProps {
20
+ /** The big primary value — typically a day-of-month number, but any short
21
+ * string works (the caller formats it). */
22
+ value: number | string;
23
+ /** Small uppercase band above the value, e.g. a month label ("MAY"). */
24
+ topLabel?: string;
25
+ /** Muted line below the value, e.g. "10h" or a short count. */
26
+ subLabel?: string;
27
+ /** Selected state. For interactive tiles this drives the amber accent +
28
+ * `aria-pressed`; ignored for read-only tiles (they always render "on"). */
29
+ selected?: boolean;
30
+ /** Make the tile a selectable button. When omitted the tile is a static,
31
+ * non-interactive cell. */
32
+ onToggle?: () => void;
33
+ /** Optional test id, applied only to interactive tiles. */
34
+ testId?: string;
35
+ }
36
+
37
+ export default function DateTile(props: DateTileProps): JSX.Element {
38
+ const interactive = (): boolean => !!props.onToggle;
39
+ const on = (): boolean => (interactive() ? props.selected ?? false : true);
40
+ return (
41
+ <Dynamic
42
+ component={interactive() ? "button" : "div"}
43
+ type={interactive() ? "button" : undefined}
44
+ onClick={props.onToggle}
45
+ aria-pressed={interactive() ? on() : undefined}
46
+ data-testid={interactive() ? props.testId : undefined}
47
+ style={{ width: "60px", height: "68px", flex: "0 0 auto" }}
48
+ class={`${interactive() ? "cursor-pointer" : ""} flex flex-col rounded-md overflow-hidden border transition-colors`}
49
+ classList={{
50
+ "border-amber-500/25 bg-zinc-800/40": on(),
51
+ "border-zinc-800/60 bg-zinc-900/40 opacity-50 hover:opacity-80": !on(),
52
+ }}
53
+ >
54
+ <div
55
+ style={{ height: "18px" }}
56
+ class="flex items-center justify-center text-[9px] font-semibold uppercase tracking-[0.15em] bg-zinc-800/70 text-zinc-500"
57
+ >
58
+ {props.topLabel ?? ""}
59
+ </div>
60
+ <div class="flex-1 flex flex-col items-center justify-center">
61
+ <div
62
+ class="text-xl font-semibold leading-none tabular-nums"
63
+ classList={{
64
+ "text-amber-400/90": on(),
65
+ "text-zinc-500": !on(),
66
+ }}
67
+ >
68
+ {props.value}
69
+ </div>
70
+ <Show when={props.subLabel != null && props.subLabel !== ""}>
71
+ <div
72
+ class="text-[9px] mt-0.5 tabular-nums"
73
+ classList={{
74
+ "text-zinc-500": on(),
75
+ "text-zinc-700": !on(),
76
+ }}
77
+ >
78
+ {props.subLabel}
79
+ </div>
80
+ </Show>
81
+ </div>
82
+ </Dynamic>
83
+ );
84
+ }
package/src/index.ts CHANGED
@@ -63,6 +63,7 @@ export { default as KpiCard, type KpiCardProps, type KpiTone } from "./component
63
63
  export { default as RadioCardGroup } from "./components/base/RadioCardGroup";
64
64
  export { default as FormErrorBanner } from "./components/base/FormErrorBanner";
65
65
  export { default as TagPill } from "./components/base/TagPill";
66
+ export { default as DateTile, type DateTileProps } from "./components/base/DateTile";
66
67
 
67
68
  // ---------------------------------------------------------------------------
68
69
  // Composite components