@pontive/pontkit-core 1.1.3 → 1.2.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.
Files changed (29) hide show
  1. package/README.md +6 -6
  2. package/catalog.json +1 -1
  3. package/custom-elements.json +1 -1
  4. package/dist/components/renderers/visuals/watermark/_watermark.d.ts +21 -0
  5. package/dist/components/widgets/index.d.ts +1 -1
  6. package/dist/components/widgets/pont-account-menu/index.d.ts +1 -0
  7. package/dist/components/widgets/{pont-nav-user/pont-nav-user.d.ts → pont-account-menu/pont-account-menu.d.ts} +35 -2
  8. package/dist/components/widgets/pont-account-settings/pont-account-settings.d.ts +12 -0
  9. package/dist/components/widgets/pont-account-settings/profile/classes.d.ts +9 -0
  10. package/dist/components/widgets/pont-account-settings/profile/components/account-info.d.ts +59 -12
  11. package/dist/components/widgets/pont-account-settings/profile/components/location-info.d.ts +13 -0
  12. package/dist/components/widgets/pont-account-settings/profile/components/personal-info.d.ts +19 -0
  13. package/dist/components/widgets/pont-account-settings/profile/components/urls-info.d.ts +6 -0
  14. package/dist/components/widgets/pont-account-settings/sidebar/classes.d.ts +0 -1
  15. package/dist/element-tag-map.d.ts +2 -2
  16. package/dist/index.js +724 -782
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +4115 -4001
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/primitives/components/ui/select/select-trigger.d.ts +15 -0
  21. package/dist/service/http/fetch.d.ts +3 -3
  22. package/dist/service/http/user/index.d.ts +1 -1
  23. package/dist/styles.css +222 -86
  24. package/dist/types/core/index.d.ts +1 -8
  25. package/dist/types/service/http/member/index.d.ts +1 -1
  26. package/dist/types/service/http/user/index.d.ts +1 -1
  27. package/dist/utils/format.d.ts +12 -0
  28. package/package.json +2 -2
  29. package/dist/components/widgets/pont-nav-user/index.d.ts +0 -1
@@ -2,6 +2,18 @@ import { BaseElement } from '../../../helpers';
2
2
  import { PropertyValues } from 'lit';
3
3
  import { Select } from './select';
4
4
  declare class SelectTrigger extends BaseElement {
5
+ /**
6
+ * A unique id for the trigger, placed on the inner <button>.
7
+ *
8
+ * Mirrors what pont-input and pont-textarea already do with `id`, and for the
9
+ * same reason: a <label for> can only point at the focusable control, which
10
+ * lives inside. Without it a select is the one field in a form that cannot be
11
+ * labelled, and screen readers announce it unnamed.
12
+ *
13
+ * The attribute is moved off the host so the id is not duplicated in the DOM.
14
+ */
15
+ id: string;
16
+ private _triggerId;
5
17
  get _select(): Select;
6
18
  private classObserver?;
7
19
  private parentObserver?;
@@ -10,6 +22,9 @@ declare class SelectTrigger extends BaseElement {
10
22
  private onStoreChange;
11
23
  get _containerElement(): HTMLSpanElement | null;
12
24
  protected firstUpdated(_changedProperties: PropertyValues): void;
25
+ protected updated(_changedProperties: PropertyValues): void;
26
+ /** Takes `id` off the host and keeps it for the inner button. */
27
+ private _adoptId;
13
28
  handleClick: (e: Event) => void;
14
29
  protected createRenderRoot(): HTMLElement | DocumentFragment;
15
30
  protected getAttributesToExclude(): string[];
@@ -10,9 +10,9 @@ export interface RequestOptions extends RequestInit {
10
10
  * Calls the management API on `apiBaseUrl` with the signed-in user's access
11
11
  * token.
12
12
  *
13
- * No project header is sent. The token's issuer is the project's own auth
14
- * domain, and that is what the gateway resolves the project from — a header
15
- * naming any other project would be refused. What the browser sends is exactly
13
+ * No instance header is sent. The token's issuer is the instance's own auth
14
+ * domain, and that is what the gateway resolves the instance from — a header
15
+ * naming any other instance would be refused. What the browser sends is exactly
16
16
  * the bearer, so the request needs no cookies and no credentialed CORS.
17
17
  */
18
18
  export declare function apiFetch<T>(endpoint: string, options?: RequestOptions): Promise<T>;
@@ -1,7 +1,7 @@
1
1
  import { UpdateUserRequest, User } from '../../../types';
2
2
  /**
3
3
  * The signed-in user's own profile. `/me` is the one management route a
4
- * project user's token may reach: the subject is the caller, so there is no
4
+ * instance user's token may reach: the subject is the caller, so there is no
5
5
  * identifier to pass and nothing to authorize beyond "you are you".
6
6
  */
7
7
  export declare function getUser(): Promise<User>;
package/dist/styles.css CHANGED
@@ -10286,15 +10286,26 @@ pont-scroll-area > [data-slot=scroll-area] {
10286
10286
  --pont-watermark-color-text: currentColor;
10287
10287
  --pont-watermark-muted-color-text: hsl(var(--pont-sem-color-text-secondary));
10288
10288
 
10289
+ /* The lockup's HEIGHT; its width follows the ~5:1 aspect ratio. */
10289
10290
  --pont-watermark-logo-space-size: var(--pont-ref-space-4);
10290
10291
 
10291
- --pont-watermark-logo-rect-color: currentColor;
10292
- --pont-watermark-brand-logo-rect-color: var(--pont-color-pontive);
10293
- --pont-watermark-brand-logo-path-color: var(--pont-color-on-pontive);
10294
- --pont-watermark-theme-logo-path-color: hsl(var(--pont-sem-color-bg));
10295
- --pont-watermark-muted-logo-path-color: hsl(
10296
- var(--pont-sem-color-bg-fill-secondary)
10292
+ /*
10293
+ * The old tile/glyph pair (*-logo-rect-color / *-logo-path-color) is gone
10294
+ * with the tile. `brand-logo-path-color` was --pont-color-on-pontive, i.e.
10295
+ * white, which only ever made sense knocked out of an indigo square; there is
10296
+ * nothing for it to sit on now.
10297
+ *
10298
+ * The mark keeps --pont-color-pontive, the indigo the tile carried. The
10299
+ * wordmark defaults to currentColor so it reads as part of the label.
10300
+ */
10301
+ --pont-watermark-logo-mark-color: currentColor;
10302
+ --pont-watermark-brand-logo-mark-color: var(--pont-color-pontive);
10303
+ --pont-watermark-theme-logo-mark-color: currentColor;
10304
+ --pont-watermark-muted-logo-mark-color: hsl(
10305
+ var(--pont-sem-color-text-secondary)
10297
10306
  );
10307
+
10308
+ --pont-watermark-logo-wordmark-color: currentColor;
10298
10309
  }
10299
10310
 
10300
10311
  /*
@@ -10367,7 +10378,22 @@ DIVIDER
10367
10378
  var(--pont-sem-color-bg-fill-secondary)
10368
10379
  );
10369
10380
 
10370
- --pont-account-settings-page-color-bg: hsl(
10381
+ /*
10382
+ * PAGE mode inherits the host page's ground.
10383
+ *
10384
+ * This was bg-surface-secondary — the very token pont-card reads — so the
10385
+ * cards and the slab behind them resolved to one colour at every brand and
10386
+ * in both themes, and only the card's 1px ring separated them. An embedded
10387
+ * widget has no business painting a ground anyway: it is dropped into
10388
+ * someone else's layout, with square corners against their rounded one.
10389
+ *
10390
+ * A brand that does want a distinct panel sets this token; the default is to
10391
+ * stay out of the way.
10392
+ */
10393
+ --pont-account-settings-page-color-bg: transparent;
10394
+
10395
+ /* The modal is a surface over a scrim, so it keeps a real ground. */
10396
+ --pont-account-settings-modal-content-color-bg: hsl(
10371
10397
  var(--pont-sem-color-bg-surface-secondary)
10372
10398
  );
10373
10399
 
@@ -10382,10 +10408,14 @@ DIVIDER
10382
10408
  --pont-account-settings-vertical-content-space-mb: var(--pont-ref-space-16);
10383
10409
  --pont-account-settings-close-button-space: var(--pont-ref-space-8);
10384
10410
  --pont-account-settings-watermark-space-py: var(--pont-ref-space-4);
10385
- --pont-account-settings-content-offset-ml: var(0);
10411
+ /* Was `var(0)` — not a valid var() call, so the margin-left that reads it was
10412
+ * dropped and computed 0px. Stated as the 0 it has always effectively been. */
10413
+ --pont-account-settings-content-offset-ml: 0;
10386
10414
  --pont-account-settings-overlay-color: hsl(var(--pont-ref-color-base-900) / 0.5);
10387
10415
  --pont-account-settings-overlay-z: 9998;
10388
- --pont-account-settings-title-font-size: 18px;
10416
+ /* Was a hardcoded 18px, so a brand moving the type scale left the card
10417
+ * titles behind. --pont-sem-font-size-lg is the 18px step. */
10418
+ --pont-account-settings-title-font-size: var(--pont-sem-font-size-lg);
10389
10419
  --pont-account-settings-title-gap: var(--pont-ref-space-2);
10390
10420
  --pont-account-settings-card-header-space-px: var(--pont-ref-space-4);
10391
10421
  --pont-account-settings-card-header-space-py: var(--pont-ref-space-2);
@@ -10406,7 +10436,9 @@ DIVIDER
10406
10436
  --pont-account-settings-sidebar-tab-spacing-bottom: var(--pont-ref-space-2);
10407
10437
  --pont-account-settings-sidebar-burger-padding: var(--pont-ref-space-2);
10408
10438
  --pont-account-settings-sidebar-burger-label-left: var(--pont-ref-space-2);
10409
- --pont-account-settings-sidebar-burger-label-font-size: 18px;
10439
+ --pont-account-settings-sidebar-burger-label-font-size: var(
10440
+ --pont-sem-font-size-lg
10441
+ );
10410
10442
  --pont-account-settings-sidebar-drawer-body-space: var(--pont-ref-space-4);
10411
10443
  --pont-account-settings-sidebar-body-height: 100%;
10412
10444
  --pont-account-settings-security-panel-max-width: 42rem;
@@ -10446,7 +10478,18 @@ DIVIDER
10446
10478
  var(--pont-sem-color-bg-fill-secondary)
10447
10479
  );
10448
10480
  --pont-sidebar-tab-trigger-burger-default-color-bg-active: inherit;
10449
- --pont-account-settings-card-radius: 0.5rem;
10481
+ /*
10482
+ * There is deliberately no --pont-account-settings-card-radius here. It was a
10483
+ * hardcoded 0.5rem overriding --pont-card-radius, which normally reads
10484
+ * --pont-sem-radius-layout off the single --pont-ref-radius that branding-svc
10485
+ * drives — so these cards were the one place in the widget a brand's radius
10486
+ * could not reach.
10487
+ */
10488
+
10489
+ --pont-account-settings-edit-card-shadow: var(--pont-sem-shadow-form);
10490
+ --pont-account-settings-skeleton-sidebar-width: 110px;
10491
+ --pont-account-settings-skeleton-tab-height: var(--pont-ref-space-8);
10492
+ --pont-account-settings-skeleton-card-height: calc(var(--pont-ref-space-1) * 40);
10450
10493
  --pont-account-settings-info-card-button-space-px-lg: var(--pont-ref-space-4);
10451
10494
  --pont-account-settings-modal-content-space-py: var(--pont-ref-space-2);
10452
10495
  --pont-account-settings-modal-content-space-px: var(--pont-ref-space-4);
@@ -10455,7 +10498,10 @@ DIVIDER
10455
10498
  --pont-account-settings-modal-radius: var(--pont-modal-radius);
10456
10499
  --pont-account-settings-modal-space-min-width: var(--pont-modal-space-min-width);
10457
10500
  --pont-account-settings-modal-color-bg: var(--pont-modal-color-bg);
10458
- --pont-account-settings-modal-content-max-height: calc(100vh-100px);
10501
+ /* calc() needs whitespace around the operator; `100vh-100px` parsed as a
10502
+ * single bad token, so the whole value was invalid and the modal's
10503
+ * max-height constraint never applied. */
10504
+ --pont-account-settings-modal-content-max-height: calc(100vh - 100px);
10459
10505
  --pont-account-settings-modal-content-height: 864px;
10460
10506
  --pont-member-management-modal-content-min-height: 50vh;
10461
10507
  --pont-account-settings-modal-width-border: var(--pont-modal-width-border);
@@ -10481,9 +10527,12 @@ DIVIDER
10481
10527
  --pont-account-info-verification-form-card-color-bg: hsl(
10482
10528
  var(--pont-sem-color-bg-fill-secondary)
10483
10529
  );
10484
- --pont-account-info-avatar-space-size: calc(var(--pont-ref-space-1) * 37);
10530
+ /* 72px. Was 148px (space-1 * 37), sized for a standalone avatar column; as a
10531
+ * row in the field list that dwarfed the card. */
10532
+ --pont-account-info-avatar-space-size: calc(var(--pont-ref-space-1) * 18);
10485
10533
  --pont-account-info-avatar-color-border: hsl(var(--pont-sem-color-border));
10486
- --pont-account-info-avatar-width-border: 1px;
10534
+ --pont-account-info-avatar-width-border: var(--pont-sem-width-border);
10535
+ --pont-account-info-avatar-shadow: var(--pont-sem-shadow-overlay);
10487
10536
  }
10488
10537
 
10489
10538
  /* Sidebar */
@@ -10493,13 +10542,13 @@ DIVIDER
10493
10542
  --pont-sidebar-color-text: hsl(var(--pont-sem-color-text));
10494
10543
  }
10495
10544
 
10496
- /* nav-user */
10545
+ /* account-menu */
10497
10546
  :root {
10498
- --pont-nav-user-button-space-py: var(--pont-ref-space-2);
10499
- --pont-nav-user-popover-item-color-bg-hover: hsl(
10547
+ --pont-account-menu-button-space-py: var(--pont-ref-space-2);
10548
+ --pont-account-menu-popover-item-color-bg-hover: hsl(
10500
10549
  var(--pont-sem-color-bg-fill-secondary)
10501
10550
  );
10502
- --pont-nav-user-dropdown-menu-content-space-p: var(--pont-ref-space-2);
10551
+ --pont-account-menu-dropdown-menu-content-space-p: var(--pont-ref-space-2);
10503
10552
  }
10504
10553
 
10505
10554
  /* account info */
@@ -11549,47 +11598,58 @@ pont-watermark > [part="watermark"][data-variant="muted"] {
11549
11598
  * ----------------------------------------
11550
11599
  */
11551
11600
 
11601
+ /*
11602
+ * Sized by HEIGHT, not as a square.
11603
+ *
11604
+ * The old mark was an 800x800 tile and this rule set width and height to the
11605
+ * same token. The lockup is ~5:1, so keeping that would squash the wordmark
11606
+ * into an unreadable 16px box.
11607
+ */
11552
11608
  pont-watermark [part="watermark-logo"] {
11553
- width: var(--pont-watermark-logo-space-size);
11554
11609
  height: var(--pont-watermark-logo-space-size);
11610
+ width: auto;
11555
11611
  }
11556
11612
 
11557
- pont-watermark > [part="watermark"] [part="watermark-logo"] > .pontive-logo-rect {
11558
- fill: var(--pont-watermark-logo-rect-color);
11613
+ /* The mark carries the brand colour the old tile did. */
11614
+ pont-watermark > [part="watermark"] [part="watermark-logo"] .pontive-logo-mark {
11615
+ fill: var(--pont-watermark-logo-mark-color);
11559
11616
  }
11560
11617
 
11561
11618
  pont-watermark
11562
11619
  > [part="watermark"][data-variant="brand"]
11563
11620
  [part="watermark-logo"]
11564
- > .pontive-logo-rect {
11565
- fill: var(--pont-watermark-brand-logo-rect-color);
11621
+ .pontive-logo-mark {
11622
+ fill: var(--pont-watermark-brand-logo-mark-color);
11566
11623
  }
11567
11624
 
11568
11625
  pont-watermark
11569
- > [part="watermark"][data-variant="brand"]
11626
+ > [part="watermark"][data-variant="theme"]
11570
11627
  [part="watermark-logo"]
11571
- > .pontive-logo-path {
11572
- fill: var(--pont-watermark-brand-logo-path-color);
11628
+ .pontive-logo-mark {
11629
+ fill: var(--pont-watermark-theme-logo-mark-color);
11573
11630
  }
11574
11631
 
11575
11632
  pont-watermark
11576
- > [part="watermark"][data-variant="theme"]
11633
+ > [part="watermark"][data-variant="muted"]
11577
11634
  [part="watermark-logo"]
11578
- > .pontive-logo-path {
11579
- fill: var(--pont-watermark-theme-logo-path-color);
11635
+ .pontive-logo-mark {
11636
+ fill: var(--pont-watermark-muted-logo-mark-color);
11580
11637
  }
11581
11638
 
11639
+ /*
11640
+ * The wordmark tracks the label. Its default is currentColor, so "Powered by"
11641
+ * and "Pontive" stay one line of text in every variant — including the muted
11642
+ * one, where the root already sets a dimmer colour.
11643
+ */
11582
11644
  pont-watermark
11583
- > [part="watermark"][data-variant="muted"]
11645
+ > [part="watermark"]
11584
11646
  [part="watermark-logo"]
11585
- > .pontive-logo-path {
11586
- fill: var(--pont-watermark-muted-logo-path-color);
11647
+ .pontive-logo-wordmark {
11648
+ fill: var(--pont-watermark-logo-wordmark-color);
11587
11649
  }
11588
-
11589
11650
  pont-paginator pont-input input {
11590
11651
  width: 36px !important;
11591
11652
  }
11592
-
11593
11653
  pont-multi-email-input div[part="input-wrapper"] {
11594
11654
  display: flex;
11595
11655
  flex-wrap: wrap;
@@ -11833,10 +11893,26 @@ pont-multi-select-filter .pont-py-dropdown-menu-label-space-py {
11833
11893
  box-shadow: none !important;
11834
11894
  }
11835
11895
 
11836
- pont-account-settings {
11837
- --pont-card-radius: var(--pont-account-settings-card-radius);
11838
- }
11896
+ /*
11897
+ * No --pont-card-radius override here.
11898
+ *
11899
+ * It used to be pinned to --pont-account-settings-card-radius, a hardcoded
11900
+ * 0.5rem, which took these cards OUT of the brand radius scale: pont-card
11901
+ * normally reads --pont-sem-radius-layout, and that scale derives from the
11902
+ * single --pont-ref-radius that branding-svc's ReferenceTokens.Radius drives.
11903
+ * A project asking for square or extra-round corners got 8px here regardless.
11904
+ */
11839
11905
 
11906
+ /*
11907
+ * PAGE mode paints no ground of its own.
11908
+ *
11909
+ * The widget is embedded in the host's page, so a background here is a slab of
11910
+ * Pontive colour dropped into someone else's layout — and it was
11911
+ * bg-surface-secondary, the SAME token pont-card reads, so the four cards came
11912
+ * out exactly their own container's colour in every theme and at every brand.
11913
+ * No brand value could separate them. The cards carry the surface; the host
11914
+ * carries the ground.
11915
+ */
11840
11916
  pont-account-settings[mode="PAGE"] {
11841
11917
  background-color: var(--pont-account-settings-page-color-bg);
11842
11918
  }
@@ -11941,7 +12017,7 @@ pont-profile pont-card[part="personal-info-card"][editing="true"] {
11941
12017
  pont-profile
11942
12018
  pont-card[part="personal-info-card"][editing="true"]
11943
12019
  > [data-slot="card"] {
11944
- box-shadow: 0 4px 4px -2px hsla(0, 0%, 0%, 0.1);
12020
+ box-shadow: var(--pont-account-settings-edit-card-shadow);
11945
12021
  border: var(--pont-card-width-ring) solid var(--pont-card-color-ring);
11946
12022
  }
11947
12023
 
@@ -11960,7 +12036,7 @@ pont-profile pont-popover[part="account-info-popover"] {
11960
12036
  pont-profile
11961
12037
  pont-card[part="urls-info-card"][editing="true"]
11962
12038
  > [data-slot="card"] {
11963
- box-shadow: 0 4px 4px -2px hsla(0, 0%, 0%, 0.1);
12039
+ box-shadow: var(--pont-account-settings-edit-card-shadow);
11964
12040
  border: var(--pont-card-width-ring) solid var(--pont-card-color-ring);
11965
12041
  }
11966
12042
 
@@ -11985,7 +12061,7 @@ pont-profile pont-card[part="location-info-card"][editing="true"] {
11985
12061
  pont-profile
11986
12062
  pont-card[part="location-info-card"][editing="true"]
11987
12063
  > [data-slot="card"] {
11988
- box-shadow: 0 4px 4px -2px hsla(0, 0%, 0%, 0.1);
12064
+ box-shadow: var(--pont-account-settings-edit-card-shadow);
11989
12065
  border: var(--pont-card-width-ring) solid var(--pont-card-color-ring);
11990
12066
  }
11991
12067
 
@@ -11998,14 +12074,32 @@ pont-account-settings div[part="page-content"] {
11998
12074
  background-color: var(--pont-account-settings-page-color-bg);
11999
12075
  }
12000
12076
 
12077
+ /*
12078
+ * The modal DOES own its ground — it is a surface floating over a scrim, not
12079
+ * something embedded in a host layout — so it reads its own token rather than
12080
+ * the page one. They used to share --pont-account-settings-page-color-bg,
12081
+ * which is why the page container could not be quietened without also
12082
+ * stripping the modal's background.
12083
+ *
12084
+ * No border declaration: the duplicate of this rule further down set
12085
+ * `border: none`, so the modal border here never applied. Kept the surviving
12086
+ * behaviour, dropped the rule that pretended otherwise.
12087
+ */
12001
12088
  pont-account-settings div[part="page-content-modal"] {
12002
- background-color: var(--pont-account-settings-page-color-bg);
12003
- border: var(--pont-modal-width-border) solid var(--pont-modal-color-border);
12089
+ background-color: var(--pont-account-settings-modal-content-color-bg);
12090
+ border: none;
12004
12091
  }
12005
12092
 
12093
+ /*
12094
+ * The colour slot held the WIDTH token, so the shorthand read
12095
+ * `1px solid 1px` — invalid, dropped whole, computed `0px none`. The divider
12096
+ * has never rendered, and --pont-account-settings-card-header-color-border
12097
+ * (wired to --pont-sem-color-border) had no consumer, so a brand's border
12098
+ * colour could not reach card headers either.
12099
+ */
12006
12100
  pont-account-settings pont-card-header {
12007
12101
  border-bottom: var(--pont-account-settings-card-header-width-border) solid
12008
- var(--pont-account-settings-card-header-width-border);
12102
+ var(--pont-account-settings-card-header-color-border);
12009
12103
  }
12010
12104
 
12011
12105
  pont-account-settings {
@@ -12186,10 +12280,19 @@ pont-account-settings .pont-account-settings-display-row-action {
12186
12280
  justify-self: end;
12187
12281
  }
12188
12282
 
12283
+ /*
12284
+ * A row, not a grid.
12285
+ *
12286
+ * This declared `grid-template-columns: var(--pont-account-settings-account-display-grid)`
12287
+ * against a token that is defined nowhere, so the value was invalid and the
12288
+ * grid collapsed to one implicit column — the label/value alignment came from
12289
+ * the inner flex row and the label's min-width all along. Saying that outright
12290
+ * beats a grid that only appeared to work.
12291
+ */
12189
12292
  pont-account-settings .pont-account-settings-account-grid {
12190
- display: grid;
12191
- grid-template-columns: var(--pont-account-settings-account-display-grid);
12293
+ display: flex;
12192
12294
  align-items: center;
12295
+ width: 100%;
12193
12296
  gap: var(--pont-account-settings-card-input-gap);
12194
12297
  }
12195
12298
 
@@ -12206,13 +12309,29 @@ pont-account-settings .pont-account-settings-account-details {
12206
12309
  flex: 1;
12207
12310
  }
12208
12311
 
12312
+ /*
12313
+ * The avatar sits in the value column of its own row now, so it no longer
12314
+ * centres itself (`margin-inline: auto`) or reserves padding for a button
12315
+ * pinned 20px in from an edge it did not know the size of. It is just an
12316
+ * inline-block box the edit button anchors to.
12317
+ */
12209
12318
  pont-account-settings .pont-account-settings-avatar-wrapper {
12210
12319
  position: relative;
12211
- display: flex;
12212
- margin-inline: auto;
12213
- padding-inline: var(--pont-account-settings-avatar-wrapper-space-px);
12214
- padding-bottom: var(--pont-account-settings-avatar-wrapper-space-pb);
12215
- margin-block: var(--pont-account-settings-avatar-wrapper-space-my);
12320
+ display: inline-flex;
12321
+ width: -moz-fit-content;
12322
+ width: fit-content;
12323
+ }
12324
+
12325
+ /*
12326
+ * Anchored to the disc's bottom-right and pulled half onto it, so the offset
12327
+ * holds at any avatar size. The old `bottom-5 right-5` was measured against a
12328
+ * 148px disc and landed off the edge as soon as that changed.
12329
+ */
12330
+ pont-account-settings .pont-account-settings-avatar-edit {
12331
+ position: absolute;
12332
+ right: 0;
12333
+ bottom: 0;
12334
+ transform: translate(25%, 25%);
12216
12335
  }
12217
12336
 
12218
12337
  pont-account-settings .pont-account-settings-avatar-menu-item {
@@ -12296,19 +12415,12 @@ pont-account-settings .pont-account-settings-avatar-menu-item:last-child {
12296
12415
  margin-bottom: 0;
12297
12416
  }
12298
12417
 
12299
- pont-profile .pont-account-settings-row-layout {
12300
- display: grid;
12301
- grid-template-columns: var(--pont-account-settings-form-grid-template);
12302
- align-items: center;
12303
- -moz-column-gap: var(--pont-account-settings-card-input-gap);
12304
- column-gap: var(--pont-account-settings-card-input-gap);
12305
- }
12306
-
12307
- @media (min-width: 768px) {
12308
- pont-profile .pont-account-settings-row-layout {
12309
- grid-template-columns: var(--pont-account-settings-form-grid-template-md);
12310
- }
12311
- }
12418
+ /*
12419
+ * .pont-account-settings-row-layout is gone. It set display:grid with a
12420
+ * grid-template-columns token that was never defined, on the same element as
12421
+ * .pont-account-settings-form-body — which sets display:flex and wins on
12422
+ * specificity. Neither half of the rule ever took effect.
12423
+ */
12312
12424
 
12313
12425
  pont-profile .pont-account-settings-column-layout {
12314
12426
  display: flex;
@@ -12365,15 +12477,11 @@ pont-security-settings .pont-account-settings-security-icon {
12365
12477
  height: var(--pont-account-settings-security-icon-size);
12366
12478
  }
12367
12479
 
12368
- pont-account-settings div[part="page-content-modal"] {
12369
- background-color: var(--pont-account-settings-page-color-bg);
12370
- border: none;
12371
- }
12372
-
12373
- pont-account-settings pont-card-header {
12374
- border-bottom: var(--pont-account-settings-card-header-width-border) solid
12375
- var(--pont-account-settings-card-header-width-border);
12376
- }
12480
+ /*
12481
+ * The page-content-modal and pont-card-header rules that used to sit here were
12482
+ * verbatim duplicates of the ones above. Both are declared once now, near the
12483
+ * other container and card rules.
12484
+ */
12377
12485
 
12378
12486
  pont-account-settings .pont-account-settings-link-icon {
12379
12487
  color: var(--pont-account-settings-label-color-text);
@@ -12421,6 +12529,40 @@ pont-account-settings pont-modal {
12421
12529
  --pont-modal-radius: var(--pont-account-settings-modal-radius);
12422
12530
  }
12423
12531
 
12532
+ /* ---- loading skeleton ---------------------------------------------------- */
12533
+ /*
12534
+ * Mirrors the loaded layout closely enough that nothing jumps when the profile
12535
+ * arrives: a sidebar column of two tab-sized blocks beside three card-sized
12536
+ * ones. Sizes come from the same tokens the real thing uses.
12537
+ */
12538
+ pont-account-settings div[part="loading"] {
12539
+ gap: var(--pont-ref-space-4);
12540
+ }
12541
+
12542
+ pont-account-settings .pont-account-settings-skeleton-sidebar {
12543
+ display: flex;
12544
+ flex-direction: column;
12545
+ gap: var(--pont-account-settings-card-input-gap);
12546
+ width: var(--pont-account-settings-skeleton-sidebar-width);
12547
+ flex-shrink: 0;
12548
+ }
12549
+
12550
+ pont-account-settings .pont-account-settings-skeleton-tab {
12551
+ height: var(--pont-account-settings-skeleton-tab-height);
12552
+ border-radius: var(--pont-sem-radius-action-sm);
12553
+ }
12554
+
12555
+ pont-account-settings .pont-account-settings-skeleton-cards {
12556
+ display: flex;
12557
+ flex-direction: column;
12558
+ gap: var(--pont-account-settings-card-content-gap-xl);
12559
+ }
12560
+
12561
+ pont-account-settings .pont-account-settings-skeleton-card {
12562
+ height: var(--pont-account-settings-skeleton-card-height);
12563
+ border-radius: var(--pont-sem-radius-layout);
12564
+ }
12565
+
12424
12566
  /* SideBar */
12425
12567
  pont-profile-sidebar div[part="tab-trigger"]:hover {
12426
12568
  background-color: var(--pont-sidebar-color-bg-hover);
@@ -12652,7 +12794,7 @@ pont-account-info pont-card[part="edit-form"] {
12652
12794
  }
12653
12795
 
12654
12796
  pont-account-info pont-card[part="edit-form"] > [data-slot="card"] {
12655
- box-shadow: 0 4px 4px -2px hsla(0, 0%, 0%, 0.1);
12797
+ box-shadow: var(--pont-account-settings-edit-card-shadow);
12656
12798
  border: var(--pont-card-width-ring) solid var(--pont-card-color-ring);
12657
12799
  }
12658
12800
 
@@ -12676,7 +12818,7 @@ pont-button[part="upload-image-button"] {
12676
12818
  pont-account-info pont-avatar > [data-slot="avatar"][data-size="lg"] {
12677
12819
  border: var(--pont-account-info-avatar-width-border) solid
12678
12820
  var(--pont-account-info-avatar-color-border);
12679
- box-shadow: 0 4px 6px -1px hsla(0, 0%, 0%, 0.1);
12821
+ box-shadow: var(--pont-account-info-avatar-shadow);
12680
12822
  }
12681
12823
 
12682
12824
  /* @media (max-width: 768px) {
@@ -12944,19 +13086,19 @@ pont-members-action-modal [part="highlight-name"] {
12944
13086
  color: hsl(var(--pont-sem-color-text-brand));
12945
13087
  }
12946
13088
 
12947
- pont-nav-user pont-dropdown-menu-trigger pont-button[part="trigger-button"] {
12948
- padding-bottom: var(--pont-nav-user-button-space-py);
12949
- padding-top: var(--pont-nav-user-button-space-py);
13089
+ pont-account-menu pont-dropdown-menu-trigger pont-button[part="trigger-button"] {
13090
+ padding-bottom: var(--pont-account-menu-button-space-py);
13091
+ padding-top: var(--pont-account-menu-button-space-py);
12950
13092
  height: auto !important;
12951
13093
  }
12952
13094
 
12953
- pont-nav-user pont-dropdown-menu-group {
13095
+ pont-account-menu pont-dropdown-menu-group {
12954
13096
  --pont-dropdown-menu-label-space-py: var(--pont-ref-space-0);
12955
13097
  }
12956
13098
 
12957
- pont-nav-user pont-dropdown-menu-content {
13099
+ pont-account-menu pont-dropdown-menu-content {
12958
13100
  --pont-dropdown-menu-content-space-p: var(
12959
- --pont-nav-user-dropdown-menu-content-space-p
13101
+ --pont-account-menu-dropdown-menu-content-space-p
12960
13102
  );
12961
13103
  }
12962
13104
 
@@ -13553,9 +13695,6 @@ video {
13553
13695
  .pont-bottom-0{
13554
13696
  bottom: 0px;
13555
13697
  }
13556
- .pont-bottom-5{
13557
- bottom: 1.25rem;
13558
- }
13559
13698
  .pont-left-1\/2{
13560
13699
  left: 50%;
13561
13700
  }
@@ -13622,9 +13761,6 @@ video {
13622
13761
  .pont-row-span-3{
13623
13762
  grid-row: span 3 / span 3;
13624
13763
  }
13625
- .pont-m-2{
13626
- margin: 0.5rem;
13627
- }
13628
13764
  .pont-m-auto{
13629
13765
  margin: auto;
13630
13766
  }
@@ -22,7 +22,7 @@ export interface EnvConfig {
22
22
  /**
23
23
  * Language for the sign-in UI: space-separated BCP-47 tags in descending
24
24
  * preference, e.g. `"de-DE fr-FR"`. Omit to let the server negotiate from the
25
- * browser's `Accept-Language` and then the project's default locale.
25
+ * browser's `Accept-Language` and then the instance's default locale.
26
26
  */
27
27
  locales?: string;
28
28
  /**
@@ -31,11 +31,4 @@ export interface EnvConfig {
31
31
  * `/mgmt/v1` prefix itself.
32
32
  */
33
33
  apiBaseUrl: string;
34
- /**
35
- * @deprecated Not read by the SDK. The project is carried by the access
36
- * token's issuer, so nothing here needs to name it. Kept optional so
37
- * consumers built against earlier typings still compile; remove when the
38
- * framework packages are rebuilt from this core.
39
- */
40
- projectId?: string;
41
34
  }
@@ -15,7 +15,7 @@ export interface Member {
15
15
  organization_id: string;
16
16
  organization_name: string;
17
17
  organization_slug: string;
18
- project_id: string;
18
+ instance_id: string;
19
19
  roles: {
20
20
  key: string;
21
21
  name: string;
@@ -19,7 +19,7 @@ export interface User {
19
19
  picture?: string;
20
20
  private_metadata?: Record<string, unknown>;
21
21
  profile?: string;
22
- project_id?: string;
22
+ instance_id?: string;
23
23
  status?: string;
24
24
  updated_at?: number;
25
25
  username?: string;
@@ -37,4 +37,16 @@ export declare const formatDate: (dateString: string | number) => {
37
37
  * @returns Human-readable relative time string
38
38
  */
39
39
  export declare function formatRelativeTime(timestamp: number): string;
40
+ /**
41
+ * Up to two initials for an avatar fallback.
42
+ *
43
+ * First letter of the first and last word, so "Mehdi Soltany" is MS. This used
44
+ * to be `slice(0, 2)`, which took the first two letters of whatever it was
45
+ * handed: "ME" for that name, and for an email the first two letters of the
46
+ * local part, so colleagues with similar addresses all collided.
47
+ *
48
+ * An email is reduced to its local part first — the domain is shared by every
49
+ * colleague and says nothing about who this is.
50
+ */
40
51
  export declare function getInitials(str?: string): string;
52
+ export declare function errorMessage(error: unknown, fallback: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pontive/pontkit-core",
3
- "version": "1.1.3",
3
+ "version": "1.2.0",
4
4
  "license": "MIT",
5
5
  "description": "A collection of core components for Pontive",
6
6
  "main": "dist/index.js",
@@ -27,7 +27,7 @@
27
27
  "stamp:catalog": "node scripts/stamp-catalog.mjs",
28
28
  "check:catalog": "node scripts/check-catalog.mjs",
29
29
  "integrity": "node scripts/integrity.mjs",
30
- "prepublishOnly": "node scripts/guard-publish.mjs && npm run check:names && npm run check:catalog && npm run stamp:catalog",
30
+ "prepublishOnly": "node scripts/guard-publish.mjs && npm run check:names && npm run check:catalog && npm run build && npm run stamp:catalog",
31
31
  "preview": "vite preview",
32
32
  "test": "vitest run",
33
33
  "lint": "eslint 'src/**/*.{ts,tsx}' --fix",
@@ -1 +0,0 @@
1
- export * from './pont-nav-user';