@nomideusz/svelte-calendar 1.8.0 → 1.8.2

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.
@@ -50,10 +50,14 @@ export declare function fontOf(el: Element): string;
50
50
  * that does not come from its own text (block, or a flex item with min-width: 0).
51
51
  */
52
52
  export declare function fitLabel(candidates: readonly string[], lines?: number): Attachment<HTMLElement>;
53
+ /** The badness of the loosest line but the last, were `lines` justified at `width`. */
54
+ export declare function looseness(lines: readonly string[], font: string, width: number): number;
53
55
  export declare function breakLines(text: string, font: string, width: number): string[];
54
56
  /**
55
57
  * `<p {@attach typeset(text)}>` — sets the paragraph as justified Knuth-Plass
56
58
  * lines, one block span per line, re-done on resize and after webfonts load.
59
+ * A paragraph that cannot be justified without gaps (`TOLERANCE`) goes back to
60
+ * the browser as plain text, set however the element sets it (ragged).
57
61
  * Progressive: the server-rendered text is what crawlers and no-JS get; if the
58
62
  * browser's own measure disagrees with ours (a line overflows), the plain
59
63
  * text goes back and the browser breaks it. Pass the text, not the DOM — the
package/dist/text-fit.js CHANGED
@@ -96,6 +96,23 @@ export function fitLabel(candidates, lines = 1) {
96
96
  // (10 + badness)² plus 50² for ending inside a word, plus 10000 when the line
97
97
  // above did too. ponytail: no fitness classes, no shrink; O(n·k).
98
98
  const SHY = '­';
99
+ const badness = (slackPx, spaces, space) => {
100
+ const r = slackPx / (Math.max(spaces, 1) * space * 0.5);
101
+ return Math.min(10000, 100 * r * r * r);
102
+ };
103
+ // TeX's default \tolerance. A narrow column (a phone) sometimes has no set of
104
+ // breaks that keeps every space under ~1.6× its width; justified, those lines
105
+ // read as holes, so typeset leaves that paragraph to the browser, ragged.
106
+ const TOLERANCE = 200;
107
+ /** The badness of the loosest line but the last, were `lines` justified at `width`. */
108
+ export function looseness(lines, font, width) {
109
+ const measure = (s) => measureNaturalWidth(prepareWithSegments(s, font));
110
+ const space = measure('a a') - measure('aa');
111
+ let worst = 0;
112
+ for (const l of lines.slice(0, -1))
113
+ worst = Math.max(worst, badness(width - measure(l), l.split(' ').length - 1, space));
114
+ return worst;
115
+ }
99
116
  export function breakLines(text, font, width) {
100
117
  const measure = (s) => measureNaturalWidth(prepareWithSegments(s, font));
101
118
  const boxes = [];
@@ -119,10 +136,6 @@ export function breakLines(text, font, width) {
119
136
  const bw = boxes.map(measure);
120
137
  const space = measure('a a') - measure('aa');
121
138
  const hyphen = measure('-');
122
- const badness = (slackPx, spaces) => {
123
- const r = slackPx / (Math.max(spaces, 1) * space * 0.5);
124
- return Math.min(10000, 100 * r * r * r);
125
- };
126
139
  // best[h][k]: cheapest way to set boxes[0..k) with a break after, h = 1 when
127
140
  // that last line ended inside a word; prev[h][k]: [start of that line, its h].
128
141
  const best = [new Array(n + 1).fill(Infinity), new Array(n + 1).fill(Infinity)];
@@ -144,7 +157,7 @@ export function breakLines(text, font, width) {
144
157
  break;
145
158
  continue; // only the hyphen overflows — try the next box
146
159
  }
147
- const b = last ? 0 : badness(width - lineW, spaces);
160
+ const b = last ? 0 : badness(width - lineW, spaces, space);
148
161
  const cost = last ? 0 : (10 + b) ** 2 + (h ? 50 ** 2 : 0) + (h && ph ? 10000 : 0);
149
162
  if (best[ph][i] + cost < best[h][j + 1]) {
150
163
  best[h][j + 1] = best[ph][i] + cost;
@@ -177,6 +190,8 @@ export function breakLines(text, font, width) {
177
190
  /**
178
191
  * `<p {@attach typeset(text)}>` — sets the paragraph as justified Knuth-Plass
179
192
  * lines, one block span per line, re-done on resize and after webfonts load.
193
+ * A paragraph that cannot be justified without gaps (`TOLERANCE`) goes back to
194
+ * the browser as plain text, set however the element sets it (ragged).
180
195
  * Progressive: the server-rendered text is what crawlers and no-JS get; if the
181
196
  * browser's own measure disagrees with ours (a line overflows), the plain
182
197
  * text goes back and the browser breaks it. Pass the text, not the DOM — the
@@ -204,6 +219,10 @@ export function typeset(text) {
204
219
  'position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap';
205
220
  const set = (w) => {
206
221
  const lines = breakLines(text, font, w);
222
+ if (looseness(lines, font, w) > TOLERANCE) {
223
+ el.textContent = text;
224
+ return true;
225
+ }
207
226
  const spans = lines.map((l, i) => {
208
227
  const s = document.createElement('span');
209
228
  s.setAttribute('aria-hidden', 'true');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomideusz/svelte-calendar",
3
- "version": "1.8.0",
3
+ "version": "1.8.2",
4
4
  "description": "A themeable Svelte 5 calendar: day, week, scrolling-week and month views, agenda lists, touch-first mobile layouts, drag-and-drop, timezones, a headless API and an embeddable web component.",
5
5
  "type": "module",
6
6
  "sideEffects": [
package/widget/widget.js CHANGED
@@ -21056,5 +21056,15 @@ createHTML: (html) => {
21056
21056
  return props;
21057
21057
  }
21058
21058
  };
21059
- if (!customElements.get("day-calendar")) customElements.define("day-calendar", DayCalendarElement);
21059
+ if (!customElements.get("day-calendar")) {
21060
+ customElements.define("day-calendar", DayCalendarElement);
21061
+ const registry = customElements;
21062
+ for (const el of document.querySelectorAll("day-calendar")) {
21063
+ if (el instanceof DayCalendarElement) continue;
21064
+ try {
21065
+ registry.initialize?.(el);
21066
+ } catch {}
21067
+ customElements.upgrade(el);
21068
+ }
21069
+ }
21060
21070
  })();