@kengcom202/kcore-ui 0.6.0 → 0.7.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
|
@@ -8,7 +8,7 @@ Angular 22 UI กลาง — ไม่พึ่งไลบรารีภา
|
|
|
8
8
|
- `<app-search-select>` — dropdown พิมพ์ค้นหาได้ ค่าเป็น `value` ของ `SearchOption` (`''` = ไม่ระบุ) ปรับสีด้วย `--kc-ss-*`
|
|
9
9
|
- `provideThaiPasteFix()` — ใส่ใน `app.config.ts` ครั้งเดียว แก้ข้อความไทยที่คัดลอกจาก PDF (□ แทนวรรณยุกต์, ช่องว่างหน้าวรรณยุกต์, "ํา") ตอนวางลงทุกช่อง
|
|
10
10
|
- หน้าบัญชีผู้ใช้กลาง — `provideKcAuth({...})` + `kcAuthInterceptor` + `kcAuthRoutes()` (`/login`, `/register`, `/sso-callback`, `/thaid-callback`) — ปุ่ม SSO (`sso`) และ ThaiD (`thaid` เข้าสู่ระบบอย่างเดียว)
|
|
11
|
-
และ `<kc-profile>`, `<kc-config-users>`, `<kc-config-kcllu>` คู่กับ `kcAuthGuard` / `kcAdminGuard`, `KcAuthService` — API ต้องทำ endpoint ตามสัญญาใน
|
|
11
|
+
และ `<kc-profile>`, `<kc-config-users>`, `<kc-config-kcllu>` คู่กับ `kcAuthGuard` / `kcAdminGuard`, `KcAuthService` — API ต้องทำ endpoint ตามสัญญาใน `README_NPM.md` ของรีโป kcore
|
|
12
12
|
- utils: `toBuddhistText`, `toChristianText`, `parseDate`, `formatDate`, `fixThaiText`
|
|
13
13
|
|
|
14
14
|
```ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
|
-
import { ApplicationRef, CSP_NONCE, Component, DOCUMENT, DestroyRef, Directive, ElementRef, EnvironmentInjector, Injectable, InjectionToken, NgZone, ViewChild, ViewEncapsulation, computed, createComponent, forwardRef, inject, input, makeEnvironmentProviders, provideEnvironmentInitializer, signal } from "@angular/core";
|
|
2
|
+
import { ApplicationRef, CSP_NONCE, Component, DOCUMENT, DestroyRef, Directive, ElementRef, EnvironmentInjector, Injectable, InjectionToken, NgZone, ViewChild, ViewEncapsulation, computed, createComponent, effect, forwardRef, inject, input, makeEnvironmentProviders, provideEnvironmentInitializer, signal, untracked } from "@angular/core";
|
|
3
3
|
import * as i1 from "@angular/forms";
|
|
4
4
|
import { FormBuilder, FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, Validators } from "@angular/forms";
|
|
5
5
|
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
|
|
@@ -1610,6 +1610,8 @@ const kcAuthInterceptor = (req, next) => {
|
|
|
1610
1610
|
const STYLE_ID = "kcore-auth-styles";
|
|
1611
1611
|
const AUTH_CSS = `
|
|
1612
1612
|
.kc-auth-screen, .kc-auth-page, .kc-auth-modal-bg {
|
|
1613
|
+
/* ค่าเริ่มต้นใช้ฟอนต์ของเว็บ — เว็บที่ body ใช้ฟอนต์เฉพาะทาง (เช่น TH Sarabun ของหน้าพิมพ์) ตั้งฟอนต์ของหน้าชุดนี้แยกได้ */
|
|
1614
|
+
font-family: var(--kc-auth-font-family, inherit);
|
|
1613
1615
|
font-size: var(--kc-auth-font-size, 14px);
|
|
1614
1616
|
color: var(--kc-auth-text, #3a2a3a);
|
|
1615
1617
|
line-height: 1.5;
|
|
@@ -1618,6 +1620,8 @@ const AUTH_CSS = `
|
|
|
1618
1620
|
|
|
1619
1621
|
/* ---- หน้าเต็มจอ (login / register / sso-callback) ---- */
|
|
1620
1622
|
.kc-auth-screen {
|
|
1623
|
+
/* border-box: padding อยู่ใน 100vh — ไม่งั้นสูงเกินจอ 48px และมี scrollbar ทั้งที่เนื้อหาน้อย */
|
|
1624
|
+
box-sizing: border-box;
|
|
1621
1625
|
min-height: 100vh;
|
|
1622
1626
|
display: flex;
|
|
1623
1627
|
align-items: center;
|
|
@@ -1627,16 +1631,23 @@ const AUTH_CSS = `
|
|
|
1627
1631
|
}
|
|
1628
1632
|
.kc-auth-card {
|
|
1629
1633
|
width: 100%;
|
|
1630
|
-
max-width: 380px;
|
|
1631
|
-
|
|
1634
|
+
max-width: var(--kc-auth-card-width, 380px);
|
|
1635
|
+
/* ขนาดกรอบของหน้าเต็มจอปรับได้ เช่น สูง 80vh แล้วขยายตัวอักษร/ช่องกรอก/โลโก้ตามความสูงจอ — ค่าเริ่มต้น = ขนาดเดิม */
|
|
1636
|
+
min-height: var(--kc-auth-card-height, auto);
|
|
1637
|
+
display: flex;
|
|
1638
|
+
flex-direction: column;
|
|
1639
|
+
justify-content: center;
|
|
1640
|
+
padding: var(--kc-auth-card-padding, 28px 28px 24px);
|
|
1641
|
+
font-size: var(--kc-auth-card-font-size, inherit);
|
|
1632
1642
|
background: var(--kc-auth-bg, #fff);
|
|
1633
1643
|
border: 1px solid var(--kc-auth-border, #f3e1f3);
|
|
1634
1644
|
border-radius: var(--kc-auth-radius, 14px);
|
|
1635
1645
|
box-shadow: 0 12px 36px rgba(204, 102, 204, 0.12);
|
|
1636
1646
|
}
|
|
1637
|
-
.kc-auth-card.wide { max-width: 560px; }
|
|
1647
|
+
.kc-auth-card.wide { max-width: var(--kc-auth-card-wide-width, 560px); }
|
|
1638
1648
|
.kc-auth-card.center { text-align: center; }
|
|
1639
|
-
.kc-auth-
|
|
1649
|
+
.kc-auth-card .kc-auth-input, .kc-auth-card .kc-auth-btn { height: var(--kc-auth-card-input-height, var(--kc-auth-input-height, 40px)); }
|
|
1650
|
+
.kc-auth-logo { display: block; max-height: var(--kc-auth-logo-height, 72px); max-width: 100%; margin: 0 auto 12px; }
|
|
1640
1651
|
.kc-auth-title { margin: 0; font-size: 1.35em; font-weight: 600; text-align: center; }
|
|
1641
1652
|
.kc-auth-subtitle { margin: 4px 0 20px; color: var(--kc-auth-muted, #806f80); text-align: center; }
|
|
1642
1653
|
.kc-auth-footer { margin: 18px 0 0; text-align: center; color: var(--kc-auth-muted, #806f80); font-size: 0.93em; }
|
|
@@ -1699,6 +1710,8 @@ const AUTH_CSS = `
|
|
|
1699
1710
|
.kc-auth-pw > .kc-auth-input { padding-right: 42px; }
|
|
1700
1711
|
.kc-auth-pw > input::-ms-reveal, .kc-auth-pw > input::-ms-clear { display: none; }
|
|
1701
1712
|
.kc-auth-pw-toggle {
|
|
1713
|
+
/* <button> ไม่รับขนาดตัวอักษรจากแม่ (browser ตั้ง ~13px) — ต้อง inherit ไม่งั้นขนาด em ของไอคอนไม่ขยายตามกรอบ */
|
|
1714
|
+
font: inherit;
|
|
1702
1715
|
position: absolute;
|
|
1703
1716
|
top: 50%;
|
|
1704
1717
|
right: 5px;
|
|
@@ -1727,6 +1740,20 @@ const AUTH_CSS = `
|
|
|
1727
1740
|
--kc-ss-border: var(--kc-auth-input-border, #e9cde9);
|
|
1728
1741
|
--kc-ss-text: var(--kc-auth-text, #3a2a3a);
|
|
1729
1742
|
}
|
|
1743
|
+
.kc-auth-card .kc-auth-field .kc-ss { --kc-ss-height: var(--kc-auth-card-input-height, var(--kc-auth-input-height, 40px)); }
|
|
1744
|
+
/* ในกรอบหน้าเต็มจอ ขนาดย่อยทั้งหมดเป็น em ของตัวอักษรในกรอบ (= px เดิมที่ 14px) — ตั้ง --kc-auth-card-font-size
|
|
1745
|
+
แล้วไอคอน ระยะห่าง และ padding ขยาย/หดตามสัดส่วนเดียวกัน */
|
|
1746
|
+
.kc-auth-card .kc-auth-logo { margin-bottom: 0.86em; }
|
|
1747
|
+
.kc-auth-card .kc-auth-subtitle { margin: 0.3em 0 1.43em; }
|
|
1748
|
+
.kc-auth-card .kc-auth-footer { margin-top: 1.3em; }
|
|
1749
|
+
.kc-auth-card .kc-auth-field { gap: 0.3em; margin-bottom: 0.86em; }
|
|
1750
|
+
.kc-auth-card .kc-auth-input { padding: 0 0.72em; border-radius: 0.57em; }
|
|
1751
|
+
.kc-auth-card .kc-auth-pw > .kc-auth-input { padding-right: 3em; }
|
|
1752
|
+
.kc-auth-card .kc-auth-pw-toggle { right: 0.36em; width: 2.3em; height: 2.3em; border-radius: 0.43em; }
|
|
1753
|
+
.kc-auth-card .kc-auth-pw-toggle svg { width: 1.36em; height: 1.36em; }
|
|
1754
|
+
.kc-auth-card .kc-auth-btn { padding: 0 1.15em; border-radius: 0.57em; gap: 0.43em; }
|
|
1755
|
+
.kc-auth-card .kc-auth-btn-row { gap: 0.72em; margin-top: 0.43em; }
|
|
1756
|
+
.kc-auth-card .kc-auth-alert { padding: 0.72em 0.86em; margin-bottom: 1em; border-radius: 0.43em; }
|
|
1730
1757
|
.kc-auth-value { padding: 8px 0; }
|
|
1731
1758
|
.kc-auth-field-error { color: var(--kc-auth-danger, #c62828); font-size: 0.86em; }
|
|
1732
1759
|
.kc-auth-hint { margin: 2px 0 0; color: var(--kc-auth-muted, #806f80); font-size: 0.86em; }
|
|
@@ -1777,6 +1804,7 @@ const AUTH_CSS = `
|
|
|
1777
1804
|
/* ปิดรหัสผ่าน: ปุ่ม SSO ปุ่มเดียวตรงกลาง */
|
|
1778
1805
|
.kc-auth-sso-only { display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 8px 0 4px; }
|
|
1779
1806
|
.kc-auth-sso-only > .kc-auth-btn { min-width: 75%; height: 46px; padding: 0 24px; font-size: 1.05em; }
|
|
1807
|
+
.kc-auth-card .kc-auth-sso-only > .kc-auth-btn { height: calc(var(--kc-auth-card-input-height, var(--kc-auth-input-height, 40px)) * 1.15); padding: 0 1.7em; }
|
|
1780
1808
|
.kc-auth-btn.block { display: flex; width: 100%; }
|
|
1781
1809
|
.kc-auth-btn.sm { height: 30px; padding: 0 10px; font-size: 0.93em; }
|
|
1782
1810
|
.kc-auth-link { color: var(--kc-auth-accent, #a23ea2); text-decoration: none; cursor: pointer; }
|
|
@@ -3423,6 +3451,7 @@ var KcConfigUsersComponent = class KcConfigUsersComponent {
|
|
|
3423
3451
|
config = inject(KC_AUTH_CONFIG);
|
|
3424
3452
|
auth = inject(KcAuthService);
|
|
3425
3453
|
http = inject(HttpClient);
|
|
3454
|
+
org = input("", ...ngDevMode ? [{ debugName: "org" }] : /* istanbul ignore next */ []);
|
|
3426
3455
|
users = signal([], ...ngDevMode ? [{ debugName: "users" }] : /* istanbul ignore next */ []);
|
|
3427
3456
|
orgs = signal([], ...ngDevMode ? [{ debugName: "orgs" }] : /* istanbul ignore next */ []);
|
|
3428
3457
|
roles = signal([], ...ngDevMode ? [{ debugName: "roles" }] : /* istanbul ignore next */ []);
|
|
@@ -3483,9 +3512,12 @@ var KcConfigUsersComponent = class KcConfigUsersComponent {
|
|
|
3483
3512
|
}, ...ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []);
|
|
3484
3513
|
constructor() {
|
|
3485
3514
|
ensureAuthStyles();
|
|
3515
|
+
effect(() => {
|
|
3516
|
+
this.org();
|
|
3517
|
+
untracked(() => this.load());
|
|
3518
|
+
});
|
|
3486
3519
|
}
|
|
3487
3520
|
ngOnInit() {
|
|
3488
|
-
this.load();
|
|
3489
3521
|
this.http.get(`${this.config.apiBase}/user/login-methods`).subscribe({
|
|
3490
3522
|
next: (m) => {
|
|
3491
3523
|
const v = {
|
|
@@ -3534,7 +3566,9 @@ var KcConfigUsersComponent = class KcConfigUsersComponent {
|
|
|
3534
3566
|
}
|
|
3535
3567
|
load() {
|
|
3536
3568
|
this.loading.set(true);
|
|
3537
|
-
this.
|
|
3569
|
+
const org = this.org();
|
|
3570
|
+
const params = org ? { org } : {};
|
|
3571
|
+
this.http.get(`${this.config.apiBase}/config/users`, { params }).subscribe({
|
|
3538
3572
|
next: (res) => {
|
|
3539
3573
|
this.users.set(res.users ?? []);
|
|
3540
3574
|
this.orgs.set(res.orgs ?? []);
|
|
@@ -3611,6 +3645,13 @@ var KcConfigUsersComponent = class KcConfigUsersComponent {
|
|
|
3611
3645
|
type: KcConfigUsersComponent,
|
|
3612
3646
|
isStandalone: true,
|
|
3613
3647
|
selector: "kc-config-users",
|
|
3648
|
+
inputs: { org: {
|
|
3649
|
+
classPropertyName: "org",
|
|
3650
|
+
publicName: "org",
|
|
3651
|
+
isSignal: true,
|
|
3652
|
+
isRequired: false,
|
|
3653
|
+
transformFunction: null
|
|
3654
|
+
} },
|
|
3614
3655
|
host: { listeners: { "document:keydown.escape": "close()" } },
|
|
3615
3656
|
ngImport: i0,
|
|
3616
3657
|
template: `
|
|
@@ -4001,7 +4042,15 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
4001
4042
|
`
|
|
4002
4043
|
}]
|
|
4003
4044
|
}],
|
|
4004
|
-
ctorParameters: () => []
|
|
4045
|
+
ctorParameters: () => [],
|
|
4046
|
+
propDecorators: { org: [{
|
|
4047
|
+
type: i0.Input,
|
|
4048
|
+
args: [{
|
|
4049
|
+
isSignal: true,
|
|
4050
|
+
alias: "org",
|
|
4051
|
+
required: false
|
|
4052
|
+
}]
|
|
4053
|
+
}] }
|
|
4005
4054
|
});
|
|
4006
4055
|
var KcConfigKclluComponent = class KcConfigKclluComponent {
|
|
4007
4056
|
config = inject(KC_AUTH_CONFIG);
|