@lazhus/kg-ui 0.3.2 → 0.4.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.
@@ -0,0 +1,137 @@
1
+ import { LitElement as a, css as n, html as r } from "lit";
2
+ class c extends a {
3
+ static properties = {
4
+ src: { type: String },
5
+ alt: { type: String },
6
+ name: { type: String },
7
+ size: { type: String },
8
+ // tiny, small, medium, large, huge, massive
9
+ shape: { type: String },
10
+ // circle, square, rounded
11
+ status: { type: String },
12
+ // online, offline, away, busy
13
+ badge: { type: String },
14
+ // numeric or simple dot
15
+ color: { type: String }
16
+ // primary, secondary, tertiary, etc. or hex
17
+ };
18
+ static styles = n`
19
+ :host {
20
+ display: inline-block;
21
+ vertical-align: middle;
22
+ position: relative;
23
+ line-height: 0;
24
+ }
25
+
26
+ .avatar-wrapper {
27
+ display: flex;
28
+ align-items: center;
29
+ justify-content: center;
30
+ background: var(--kg-bg-secondary, #eee);
31
+ color: var(--kg-text-muted, #666);
32
+ font-weight: 700;
33
+ overflow: hidden;
34
+ user-select: none;
35
+ transition: all 0.2s ease;
36
+ position: relative;
37
+ }
38
+
39
+ .avatar-img {
40
+ width: 100%;
41
+ height: 100%;
42
+ object-fit: cover;
43
+ }
44
+
45
+ .initials {
46
+ text-transform: uppercase;
47
+ }
48
+
49
+ /* Shapes */
50
+ .circle { border-radius: 50%; }
51
+ .square { border-radius: 0; }
52
+ .rounded { border-radius: var(--kg-radius-md, 8px); }
53
+
54
+ /* Sizes */
55
+ .tiny { width: 24px; height: 24px; font-size: 0.7rem; }
56
+ .small { width: 32px; height: 32px; font-size: 0.85rem; }
57
+ .medium { width: 48px; height: 48px; font-size: 1.1rem; }
58
+ .large { width: 64px; height: 64px; font-size: 1.5rem; }
59
+ .huge { width: 96px; height: 96px; font-size: 2.2rem; }
60
+ .massive { width: 128px; height: 128px; font-size: 3rem; }
61
+
62
+ /* Status Badge */
63
+ .status-badge {
64
+ position: absolute;
65
+ bottom: 0;
66
+ right: 0;
67
+ width: 25%;
68
+ height: 25%;
69
+ border-radius: 50%;
70
+ border: 2px solid var(--kg-bg, white);
71
+ z-index: 1;
72
+ }
73
+
74
+ .online { background-color: #41ab34; }
75
+ .offline { background-color: #9e9e9e; }
76
+ .away { background-color: #fbb140; }
77
+ .busy { background-color: #db2828; }
78
+
79
+ .numeric-badge {
80
+ position: absolute;
81
+ top: -4px;
82
+ right: -4px;
83
+ background: #db2828;
84
+ color: white;
85
+ font-size: 10px;
86
+ padding: 2px 6px;
87
+ border-radius: 10px;
88
+ border: 2px solid var(--kg-bg, white);
89
+ font-weight: bold;
90
+ line-height: 1;
91
+ z-index: 2;
92
+ }
93
+
94
+ /* Semantic Colors for Avatar Background */
95
+ .primary { background-color: var(--kg-primary); color: white; }
96
+ .secondary { background-color: var(--kg-secondary); color: white; }
97
+ .tertiary { background-color: var(--kg-tertiary); color: white; }
98
+ .error { background-color: #db2828; color: white; }
99
+ .success { background-color: #41ab34; color: white; }
100
+ .warning { background-color: #fbb140; color: white; }
101
+ .info { background-color: #1367FF; color: white; }
102
+
103
+ /* Custom Color Helper */
104
+ .custom-color {
105
+ background-color: var(--avatar-bg);
106
+ color: white;
107
+ }
108
+ `;
109
+ constructor() {
110
+ super(), this.size = "medium", this.shape = "circle", this.alt = "Avatar";
111
+ }
112
+ getInitials() {
113
+ if (!this.name) return "";
114
+ const t = this.name.split(" ");
115
+ return t.length > 1 ? (t[0][0] + t[t.length - 1][0]).toUpperCase() : t[0][0].toUpperCase();
116
+ }
117
+ render() {
118
+ const e = ["primary", "secondary", "tertiary", "error", "success", "warning", "info"].includes(this.color), i = this.color && !e, o = [
119
+ "avatar-wrapper",
120
+ this.size,
121
+ this.shape,
122
+ this.color && e ? this.color : "",
123
+ i ? "custom-color" : ""
124
+ ].join(" "), s = i ? `--avatar-bg: ${this.color};` : "";
125
+ return r`
126
+ <div class="${o}" style="${s}" title="${this.name || this.alt}">
127
+ ${this.src ? r`<img class="avatar-img" src="${this.src}" alt="${this.alt}" @error=${() => this.src = ""} />` : r`<span class="initials">${this.getInitials()}</span>`}
128
+ </div>
129
+ ${this.status ? r`<div class="status-badge ${this.status} ${this.shape}"></div>` : ""}
130
+ ${this.badge ? r`<div class="numeric-badge">${this.badge}</div>` : ""}
131
+ `;
132
+ }
133
+ }
134
+ customElements.define("kg-avatar", c);
135
+ export {
136
+ c as kgavatar
137
+ };
@@ -0,0 +1,130 @@
1
+ import { LitElement as a, css as r, html as e } from "lit";
2
+ class n extends a {
3
+ static properties = {
4
+ separator: { type: String }
5
+ };
6
+ static styles = r`
7
+ :host {
8
+ display: block;
9
+ }
10
+
11
+ nav {
12
+ display: flex;
13
+ flex-wrap: wrap;
14
+ align-items: center;
15
+ gap: 0.5rem;
16
+ padding: 0;
17
+ margin: 0;
18
+ list-style: none;
19
+ font-size: 0.9rem;
20
+ color: var(--kg-text-muted, #666);
21
+ }
22
+
23
+ ::slotted(a), ::slotted(span) {
24
+ display: flex;
25
+ align-items: center;
26
+ gap: 0.25rem;
27
+ color: inherit;
28
+ text-decoration: none;
29
+ transition: color 0.2s;
30
+ }
31
+
32
+ ::slotted(a:hover) {
33
+ color: var(--kg-primary, #41ab34);
34
+ }
35
+
36
+ ::slotted(.active) {
37
+ color: var(--kg-text, #1a1a1a);
38
+ font-weight: 600;
39
+ pointer-events: none;
40
+ }
41
+
42
+ .separator {
43
+ display: flex;
44
+ align-items: center;
45
+ user-select: none;
46
+ font-size: 0.8em;
47
+ opacity: 0.5;
48
+ }
49
+ `;
50
+ constructor() {
51
+ super(), this.separator = "/";
52
+ }
53
+ _handleSlotChange(t) {
54
+ t.target.assignedNodes().filter((o) => o.nodeType === Node.ELEMENT_NODE), this.requestUpdate();
55
+ }
56
+ render() {
57
+ return e`
58
+ <nav aria-label="Breadcrumb">
59
+ <slot @slotchange="${this._handleSlotChange}"></slot>
60
+ </nav>
61
+ `;
62
+ }
63
+ }
64
+ class i extends a {
65
+ static properties = {
66
+ href: { type: String },
67
+ active: { type: Boolean, reflect: !0 },
68
+ separator: { type: String }
69
+ };
70
+ static styles = r`
71
+ :host {
72
+ display: inline-flex;
73
+ align-items: center;
74
+ gap: 0.5rem;
75
+ }
76
+
77
+ .item {
78
+ color: var(--kg-text-muted, #666);
79
+ text-decoration: none;
80
+ transition: color 0.2s;
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 0.4rem;
84
+ cursor: pointer;
85
+ }
86
+
87
+ .item:hover {
88
+ color: var(--kg-primary, #41ab34);
89
+ }
90
+
91
+ .item.active {
92
+ color: var(--kg-text, #1a1a1a);
93
+ font-weight: 600;
94
+ pointer-events: none;
95
+ }
96
+
97
+ .separator {
98
+ color: var(--kg-text-muted, #999);
99
+ opacity: 0.6;
100
+ font-size: 0.85em;
101
+ user-select: none;
102
+ margin: 0 2px;
103
+ }
104
+
105
+ :host(:last-child) .separator {
106
+ display: none;
107
+ }
108
+ `;
109
+ constructor() {
110
+ super(), this.active = !1, this.separator = "/";
111
+ }
112
+ render() {
113
+ const t = e`
114
+ <slot name="icon"></slot>
115
+ <slot></slot>
116
+ `;
117
+ return e`
118
+ ${this.href && !this.active ? e`<a class="item" href="${this.href}">${t}</a>` : e`<span class="item ${this.active ? "active" : ""}">${t}</span>`}
119
+ <span class="separator">
120
+ <slot name="separator">${this.separator}</slot>
121
+ </span>
122
+ `;
123
+ }
124
+ }
125
+ customElements.define("kg-breadcrumbs", n);
126
+ customElements.define("kg-breadcrumb-item", i);
127
+ export {
128
+ i as kgbreadcrumbitem,
129
+ n as kgbreadcrumbs
130
+ };
@@ -0,0 +1,90 @@
1
+ import { LitElement as e, css as t, html as r } from "lit";
2
+ class l extends e {
3
+ static styles = t`
4
+ :host {
5
+ display: block;
6
+ width: 100%;
7
+ }
8
+ .list-container {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: 2px;
12
+ }
13
+ ::slotted(kg-list-item:not(:last-child)) {
14
+ border-bottom: 1px solid var(--kg-border, #eee);
15
+ }
16
+ `;
17
+ render() {
18
+ return r`
19
+ <div class="list-container">
20
+ <slot></slot>
21
+ </div>
22
+ `;
23
+ }
24
+ }
25
+ class o extends e {
26
+ static properties = {
27
+ active: { type: Boolean, reflect: !0 },
28
+ clickable: { type: Boolean, reflect: !0 }
29
+ };
30
+ static styles = t`
31
+ :host {
32
+ display: block;
33
+ }
34
+ .item-wrapper {
35
+ display: flex;
36
+ align-items: center;
37
+ gap: 1rem;
38
+ padding: 0.75rem 1rem;
39
+ transition: all 0.2s ease;
40
+ background: transparent;
41
+ border-radius: var(--kg-radius-sm, 4px);
42
+ }
43
+ :host([clickable]) .item-wrapper {
44
+ cursor: pointer;
45
+ }
46
+ :host([clickable]:hover) .item-wrapper {
47
+ background: var(--kg-bg-secondary, rgba(0,0,0,0.03));
48
+ }
49
+ :host([active]) .item-wrapper {
50
+ background: var(--kg-bg-secondary, rgba(0,0,0,0.05));
51
+ border-left: 3px solid var(--kg-primary);
52
+ }
53
+ .content {
54
+ flex: 1;
55
+ display: flex;
56
+ flex-direction: column;
57
+ gap: 2px;
58
+ }
59
+ ::slotted([slot="header"]) {
60
+ margin: 0;
61
+ font-weight: 600;
62
+ font-size: 0.95rem;
63
+ color: var(--kg-text);
64
+ }
65
+ ::slotted([slot="description"]) {
66
+ margin: 0;
67
+ font-size: 0.85rem;
68
+ color: var(--kg-text-muted);
69
+ }
70
+ `;
71
+ render() {
72
+ return r`
73
+ <div class="item-wrapper">
74
+ <slot name="left"></slot>
75
+ <div class="content">
76
+ <slot name="header"></slot>
77
+ <slot name="description"></slot>
78
+ <slot></slot>
79
+ </div>
80
+ <slot name="right"></slot>
81
+ </div>
82
+ `;
83
+ }
84
+ }
85
+ customElements.define("kg-list", l);
86
+ customElements.define("kg-list-item", o);
87
+ export {
88
+ l as kglist,
89
+ o as kglistitem
90
+ };
@@ -0,0 +1,121 @@
1
+ import { LitElement as a, css as c, html as s } from "lit";
2
+ class l extends a {
3
+ static properties = {
4
+ color: { type: String },
5
+ // primary, secondary, tertiary, error, success, info, warning
6
+ size: { type: String },
7
+ // mini, tiny, small, medium, large
8
+ pill: { type: Boolean },
9
+ basic: { type: Boolean },
10
+ closable: { type: Boolean }
11
+ };
12
+ static styles = c`
13
+ :host {
14
+ display: inline-flex;
15
+ }
16
+
17
+ .tag {
18
+ display: inline-flex;
19
+ align-items: center;
20
+ justify-content: center;
21
+ padding: 0.25em 0.8em;
22
+ border-radius: var(--kg-radius-sm, 4px);
23
+ font-size: 0.85rem;
24
+ font-weight: 600;
25
+ line-height: 1;
26
+ gap: 0.4em;
27
+ background: var(--kg-bg-secondary, #eee);
28
+ color: var(--kg-text, #333);
29
+ border: 1px solid transparent;
30
+ user-select: none;
31
+ transition: all 0.2s ease;
32
+ white-space: nowrap;
33
+ }
34
+
35
+ .pill { border-radius: 100px; }
36
+
37
+ /* Sizes */
38
+ .mini { font-size: 0.65rem; padding: 0.2em 0.5em; }
39
+ .tiny { font-size: 0.75rem; padding: 0.22em 0.6em; }
40
+ .small { font-size: 0.8rem; padding: 0.25em 0.7em; }
41
+ .medium { font-size: 0.9rem; padding: 0.3em 0.85em; }
42
+ .large { font-size: 1rem; padding: 0.35em 1em; }
43
+
44
+ /* Colors */
45
+ .primary { background: var(--kg-primary); color: white; }
46
+ .secondary { background: var(--kg-secondary); color: white; }
47
+ .tertiary { background: var(--kg-tertiary); color: white; }
48
+ .error { background: #DB2828; color: white; }
49
+ .success { background: #41ab34; color: white; }
50
+ .warning { background: #FBB140; color: white; }
51
+
52
+ /* Basic (Outlined) */
53
+ .basic {
54
+ background: transparent;
55
+ border-color: currentColor;
56
+ color: var(--kg-text-muted);
57
+ }
58
+ .basic.primary { color: var(--kg-primary); }
59
+ .basic.secondary { color: var(--kg-secondary); }
60
+ .basic.tertiary { color: var(--kg-tertiary); }
61
+ .basic.error { color: #DB2828; }
62
+ .basic.success { color: #41ab34; }
63
+
64
+ .close-icon {
65
+ cursor: pointer;
66
+ opacity: 0.7;
67
+ display: flex;
68
+ align-items: center;
69
+ margin-right: -0.3em;
70
+ font-size: 1.1em;
71
+ }
72
+
73
+ .close-icon:hover {
74
+ opacity: 1;
75
+ }
76
+
77
+ /* Custom Colors */
78
+ .custom-color {
79
+ background: var(--kg-tag-color);
80
+ color: white;
81
+ }
82
+ .basic.custom-color {
83
+ background: transparent;
84
+ border-color: var(--kg-tag-color);
85
+ color: var(--kg-tag-color);
86
+ }
87
+ `;
88
+ constructor() {
89
+ super(), this.size = "medium", this.color = "";
90
+ }
91
+ _handleClose(o) {
92
+ o.stopPropagation(), this.dispatchEvent(new CustomEvent("kg-close", {
93
+ bubbles: !0,
94
+ composed: !0
95
+ }));
96
+ }
97
+ render() {
98
+ const r = ["primary", "secondary", "tertiary", "error", "success", "warning"].includes(this.color), e = this.color && !r, t = [
99
+ "tag",
100
+ this.size,
101
+ this.color && r ? this.color : "",
102
+ e ? "custom-color" : "",
103
+ this.pill ? "pill" : "",
104
+ this.basic ? "basic" : ""
105
+ ].join(" "), i = e ? `--kg-tag-color: ${this.color};` : "";
106
+ return s`
107
+ <div class="${t}" style="${i}">
108
+ <slot name="left"></slot>
109
+ <slot></slot>
110
+ <slot name="right"></slot>
111
+ ${this.closable ? s`
112
+ <span class="close-icon" @click="${this._handleClose}">✕</span>
113
+ ` : ""}
114
+ </div>
115
+ `;
116
+ }
117
+ }
118
+ customElements.define("kg-tag", l);
119
+ export {
120
+ l as kgtag
121
+ };
@@ -0,0 +1,131 @@
1
+ import { LitElement as e, css as i, html as t } from "lit";
2
+ class r extends e {
3
+ static properties = {
4
+ content: { type: String },
5
+ position: { type: String, reflect: !0 },
6
+ // top, bottom, left, right
7
+ trigger: { type: String, reflect: !0 },
8
+ // hover, click
9
+ visible: { type: Boolean, reflect: !0 }
10
+ };
11
+ static styles = i`
12
+ :host {
13
+ display: inline-block;
14
+ position: relative;
15
+ }
16
+
17
+ .tooltip-trigger {
18
+ display: inline-block;
19
+ cursor: pointer;
20
+ }
21
+
22
+ .tooltip-content {
23
+ position: absolute;
24
+ background: #333;
25
+ color: white;
26
+ padding: 0.5rem 0.75rem;
27
+ border-radius: 6px;
28
+ font-size: 0.85rem;
29
+ white-space: nowrap;
30
+ z-index: 1000;
31
+ opacity: 0;
32
+ visibility: hidden;
33
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
34
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
35
+ pointer-events: none;
36
+ }
37
+
38
+ /* Position Styles */
39
+ .top {
40
+ bottom: 100%;
41
+ left: 50%;
42
+ transform: translateX(-50%) translateY(-8px);
43
+ margin-bottom: 8px;
44
+ }
45
+ .bottom {
46
+ top: 100%;
47
+ left: 50%;
48
+ transform: translateX(-50%) translateY(8px);
49
+ margin-top: 8px;
50
+ }
51
+ .left {
52
+ top: 50%;
53
+ right: 100%;
54
+ transform: translateY(-50%) translateX(-8px);
55
+ margin-right: 8px;
56
+ }
57
+ .right {
58
+ top: 50%;
59
+ left: 100%;
60
+ transform: translateY(-50%) translateX(8px);
61
+ margin-left: 8px;
62
+ }
63
+
64
+ /* Arrow */
65
+ .tooltip-content::after {
66
+ content: '';
67
+ position: absolute;
68
+ border: 5px solid transparent;
69
+ }
70
+
71
+ .top::after { top: 100%; left: 50%; transform: translateX(-50%); border-top-color: #333; }
72
+ .bottom::after { bottom: 100%; left: 50%; transform: translateX(-50%); border-bottom-color: #333; }
73
+ .left::after { left: 100%; top: 50%; transform: translateY(-50%); border-left-color: #333; }
74
+ .right::after { right: 100%; top: 50%; transform: translateY(-50%); border-right-color: #333; }
75
+
76
+ /* Visibility Logic */
77
+ :host([trigger="hover"]:hover) .tooltip-content,
78
+ :host([visible]) .tooltip-content {
79
+ opacity: 1;
80
+ visibility: visible;
81
+ }
82
+
83
+ /* Transform Adjustment for Visible State */
84
+ :host([trigger="hover"]:hover) .tooltip-content.top,
85
+ :host([visible]) .tooltip-content.top { transform: translateX(-50%) translateY(-4px); }
86
+
87
+ :host([trigger="hover"]:hover) .tooltip-content.bottom,
88
+ :host([visible]) .tooltip-content.bottom { transform: translateX(-50%) translateY(4px); }
89
+
90
+ :host([trigger="hover"]:hover) .tooltip-content.left,
91
+ :host([visible]) .tooltip-content.left { transform: translateY(-50%) translateX(-4px); }
92
+
93
+ :host([trigger="hover"]:hover) .tooltip-content.right,
94
+ :host([visible]) .tooltip-content.right { transform: translateY(-50%) translateX(4px); }
95
+ `;
96
+ constructor() {
97
+ super(), this.position = "top", this.trigger = "hover", this.visible = !1;
98
+ }
99
+ _show() {
100
+ this.trigger === "click" && (this.visible = !this.visible);
101
+ }
102
+ _hide() {
103
+ this.trigger;
104
+ }
105
+ connectedCallback() {
106
+ super.connectedCallback(), this.trigger === "click" && document.addEventListener("click", this._handleOutsideClick.bind(this));
107
+ }
108
+ disconnectedCallback() {
109
+ super.disconnectedCallback(), document.removeEventListener("click", this._handleOutsideClick.bind(this));
110
+ }
111
+ _handleOutsideClick(o) {
112
+ this.visible && !this.contains(o.target) && (this.visible = !1);
113
+ }
114
+ render() {
115
+ return t`
116
+ <div class="tooltip-trigger"
117
+ @click="${this._show}"
118
+ role="tooltip"
119
+ aria-haspopup="true">
120
+ <slot></slot>
121
+ </div>
122
+ <div class="tooltip-content ${this.position}">
123
+ ${this.content || t`<slot name="content"></slot>`}
124
+ </div>
125
+ `;
126
+ }
127
+ }
128
+ customElements.define("kg-tooltip", r);
129
+ export {
130
+ r as kgtooltip
131
+ };