@kanso-labs/kanso-ui 0.40.8 → 0.40.9

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.
@@ -1,40 +1,55 @@
1
1
  //#region src/mark/initials.ts
2
+ const INITIAL = /^[\p{L}\p{N}\p{Extended_Pictographic}\p{Regional_Indicator}]/u;
3
+ const JOINING = /^[\p{Script=Arabic}\p{Script=Syriac}\p{Script=Mongolian}\p{Script=Nko}\p{Script=Adlam}\p{Script=Mandaic}\p{Script=Manichaean}\p{Script=Psalter_Pahlavi}\p{Script=Hanifi_Rohingya}\p{Script=Sogdian}\p{Script=Old_Uyghur}]/u;
4
+ const ZERO_WIDTH_NON_JOINER = "‌";
5
+ const TITLE = /^\p{L}{2,4}\.$/u;
6
+ const SUFFIX = /^(?:jr|sr|ii|iii|iv|\d+(?:st|nd|rd|th))\.?,?$/iu;
7
+ const TRAILING_ASIDE = /\s*[([{][^)\]}]*[)\]}]\s*$/u;
8
+ const segmenters = /* @__PURE__ */ new Map();
9
+ function graphemesOf(text, locale) {
10
+ let segmenter = segmenters.get(locale);
11
+ if (segmenter === void 0) {
12
+ segmenter = new Intl.Segmenter(locale, { granularity: "grapheme" });
13
+ segmenters.set(locale, segmenter);
14
+ }
15
+ return Array.from(segmenter.segment(text), ({ segment }) => segment);
16
+ }
17
+ /**
18
+ * The character that stands for `word`: its first grapheme that is a letter,
19
+ * a number or a picture, or its first grapheme where it has none of those,
20
+ * so something always shows. Upper-cased in the locale, and then one
21
+ * grapheme of that, since upper-casing can lengthen it: "ß" is "SS".
22
+ */
23
+ function initialOf(word, locale) {
24
+ const graphemes = graphemesOf(word, locale);
25
+ return graphemesOf((graphemes.find((grapheme) => INITIAL.test(grapheme)) ?? graphemes.at(0) ?? "").toLocaleUpperCase(locale), locale).at(0) ?? "";
26
+ }
2
27
  /**
3
28
  * One letter, where a person takes two. A person has a first name and a last
4
29
  * name to initialise; a thing usually has neither, so the same rule applied
5
30
  * to "Second Item" would produce "SI" — a pair of initials for something that
6
- * was never two words in that sense. Array.from rather than indexing, so a
7
- * name starting outside the Basic Multilingual Plane yields its whole first
8
- * character instead of half a surrogate pair.
31
+ * was never two words in that sense.
9
32
  */
10
- function initialOfThing(name) {
11
- const trimmed = name.trim();
12
- return (Array.from(trimmed)[0] ?? "").toLocaleUpperCase();
33
+ function initialOfThing(name, locale) {
34
+ return initialOf(name.trim(), locale);
13
35
  }
14
36
  /**
15
- * The first character of the first and last word, which handles both "Ada"
16
- * and "Ada Lovelace" without a separate prop for how many to take.
17
- *
18
- * A character is a grapheme, what a reader sees as one, rather than a code
19
- * point: a code point drops an accent written as a combining mark, splits an
20
- * Indic conjunct and cuts a flag or a joined emoji in half. And it is
21
- * upper-cased in the reader's locale, which is what turns a Turkish "i" into
22
- * "İ" rather than "I".
37
+ * The initials of the first and the last word, which handles both "Ada" and
38
+ * "Ada Lovelace" without a separate prop for how many to take. What a
39
+ * display name carries around the name itself is left out first: a title
40
+ * before it, a generational suffix after it, and an aside in brackets at its
41
+ * end. A name written without spaces between its words — Japanese, Chinese —
42
+ * is one word to this, and takes one initial.
23
43
  */
24
44
  function initialsOfPerson(name, locale) {
25
- const words = name.split(/\s+/u).filter(Boolean);
45
+ let words = name.replace(TRAILING_ASIDE, "").split(/\s+/u).filter(Boolean);
46
+ if (words.length > 1 && TITLE.test(words[0] ?? "")) words = words.slice(1);
47
+ if (words.length > 1 && SUFFIX.test(words.at(-1) ?? "")) words = words.slice(0, -1);
26
48
  if (words.length === 0) return "";
27
- return `${firstGrapheme(words[0] ?? "", locale)}${words.length > 1 ? firstGrapheme(words.at(-1) ?? "", locale) : ""}`.toLocaleUpperCase(locale);
28
- }
29
- const segmenters = /* @__PURE__ */ new Map();
30
- function firstGrapheme(word, locale) {
31
- let segmenter = segmenters.get(locale);
32
- if (segmenter === void 0) {
33
- segmenter = new Intl.Segmenter(locale, { granularity: "grapheme" });
34
- segmenters.set(locale, segmenter);
35
- }
36
- for (const { segment } of segmenter.segment(word)) return segment;
37
- return "";
49
+ const first = initialOf(words[0] ?? "", locale);
50
+ if (words.length === 1) return first;
51
+ const last = initialOf(words.at(-1) ?? "", locale);
52
+ return `${first}${JOINING.test(first) && JOINING.test(last) ? ZERO_WIDTH_NON_JOINER : ""}${last}`;
38
53
  }
39
54
  //#endregion
40
55
  export { initialOfThing, initialsOfPerson };
@@ -1 +1 @@
1
- {"version":3,"file":"initials.js","names":["initialOfThing","name","trimmed","trim","Array","from","toLocaleUpperCase","initialsOfPerson","locale","words","split","filter","Boolean","length","first","firstGrapheme","last","at","segmenters","Map","Intl","Segmenter","word","segmenter","get","undefined","granularity","set","segment"],"sources":["../../src/mark/initials.ts"],"sourcesContent":["// What a mark shows while it has no image: two initials for a person, one for\n// anything else. Beside the mark rather than inside `./index.tsx`, which\n// exports components alone so fast refresh keeps working for it.\n\n/**\n * One letter, where a person takes two. A person has a first name and a last\n * name to initialise; a thing usually has neither, so the same rule applied\n * to \"Second Item\" would produce \"SI\" — a pair of initials for something that\n * was never two words in that sense. Array.from rather than indexing, so a\n * name starting outside the Basic Multilingual Plane yields its whole first\n * character instead of half a surrogate pair.\n */\nfunction initialOfThing(name: string) {\n const trimmed = name.trim()\n return (Array.from(trimmed)[0] ?? '').toLocaleUpperCase()\n}\n\n/**\n * The first character of the first and last word, which handles both \"Ada\"\n * and \"Ada Lovelace\" without a separate prop for how many to take.\n *\n * A character is a grapheme, what a reader sees as one, rather than a code\n * point: a code point drops an accent written as a combining mark, splits an\n * Indic conjunct and cuts a flag or a joined emoji in half. And it is\n * upper-cased in the reader's locale, which is what turns a Turkish \"i\" into\n * \"İ\" rather than \"I\".\n */\nfunction initialsOfPerson(name: string, locale: string) {\n const words = name.split(/\\s+/u).filter(Boolean)\n if (words.length === 0) {\n return ''\n }\n const first = firstGrapheme(words[0] ?? '', locale)\n const last = words.length > 1 ? firstGrapheme(words.at(-1) ?? '', locale) : ''\n return `${first}${last}`.toLocaleUpperCase(locale)\n}\n\nconst segmenters = new Map<string, Intl.Segmenter>()\n\nfunction firstGrapheme(word: string, locale: string) {\n let segmenter = segmenters.get(locale)\n if (segmenter === undefined) {\n segmenter = new Intl.Segmenter(locale, { granularity: 'grapheme' })\n segmenters.set(locale, segmenter)\n }\n for (const { segment } of segmenter.segment(word)) {\n return segment\n }\n return ''\n}\n\nexport { initialOfThing, initialsOfPerson }\n"],"mappings":";;;;;;;;;AAYA,SAASA,eAAeC,MAAc;CACpC,MAAMC,UAAUD,KAAKE,KAAK;CAC1B,QAAQC,MAAMC,KAAKH,OAAO,CAAC,CAAC,MAAM,GAAA,CAAII,kBAAkB;AAC1D;;;;;;;;;;;AAYA,SAASC,iBAAiBN,MAAcO,QAAgB;CACtD,MAAMC,QAAQR,KAAKS,MAAM,MAAM,CAAC,CAACC,OAAOC,OAAO;CAC/C,IAAIH,MAAMI,WAAW,GACnB,OAAO;CAIT,OAAO,GAFOE,cAAcN,MAAM,MAAM,IAAID,MAElCM,IADGL,MAAMI,SAAS,IAAIE,cAAcN,MAAMQ,GAAG,EAAE,KAAK,IAAIT,MAAM,IAAI,KACnDF,kBAAkBE,MAAM;AACnD;AAEA,MAAMU,6BAAa,IAAIC,IAA4B;AAEnD,SAASJ,cAAcO,MAAcd,QAAgB;CACnD,IAAIe,YAAYL,WAAWM,IAAIhB,MAAM;CACrC,IAAIe,cAAcE,KAAAA,GAAW;EAC3BF,YAAY,IAAIH,KAAKC,UAAUb,QAAQ,EAAEkB,aAAa,WAAW,CAAC;EAClER,WAAWS,IAAInB,QAAQe,SAAS;CAClC;CACA,KAAK,MAAM,EAAEK,aAAaL,UAAUK,QAAQN,IAAI,GAC9C,OAAOM;CAET,OAAO;AACT"}
1
+ {"version":3,"file":"initials.js","names":["INITIAL","JOINING","ZERO_WIDTH_NON_JOINER","TITLE","SUFFIX","TRAILING_ASIDE","segmenters","Map","Intl","Segmenter","graphemesOf","text","locale","segmenter","get","undefined","granularity","set","Array","from","segment","initialOf","word","graphemes","chosen","find","grapheme","test","at","toLocaleUpperCase","initialOfThing","name","trim","initialsOfPerson","words","replace","split","filter","Boolean","length","slice","first","last","between"],"sources":["../../src/mark/initials.ts"],"sourcesContent":["// What a mark shows while it has no image: two initials for a person, one for\n// anything else. Beside the mark rather than inside `./index.tsx`, which\n// exports components alone so fast refresh keeps working for it.\n//\n// Both take the same rule for which character stands for a word, in\n// `initialOf`, and both work in graphemes — what a reader sees as one\n// character — in the reader's locale. A code point drops an accent written\n// as a combining mark, splits an Indic conjunct and cuts a flag or a joined\n// emoji in half; upper-casing without the locale turns a Turkish \"i\" into\n// \"I\" rather than \"İ\".\n\n// What a word's initial can be: a letter, a number, or a picture — an emoji,\n// or a flag, which is a pair of regional indicators. A word opening with\n// anything else — a bracket, a quote, the @ of a handle, the # of a channel\n// — is initialised by the first of these inside it.\nconst INITIAL = /^[\\p{L}\\p{N}\\p{Extended_Pictographic}\\p{Regional_Indicator}]/u\n\n// The scripts whose letters join to the next one. Two initials in one of\n// them, written side by side, shape into a single connected word rather than\n// two letters, so a zero-width non-joiner goes between them.\nconst JOINING =\n /^[\\p{Script=Arabic}\\p{Script=Syriac}\\p{Script=Mongolian}\\p{Script=Nko}\\p{Script=Adlam}\\p{Script=Mandaic}\\p{Script=Manichaean}\\p{Script=Psalter_Pahlavi}\\p{Script=Hanifi_Rohingya}\\p{Script=Sogdian}\\p{Script=Old_Uyghur}]/u\n\nconst ZERO_WIDTH_NON_JOINER = '‌'\n\n// A title before a name — \"Dr.\", \"Mrs.\", \"Prof.\" — which is not one of its\n// words. Two letters at least, so a first initial written \"J.\" is kept.\nconst TITLE = /^\\p{L}{2,4}\\.$/u\n\n// A generational suffix after a name — \"Jr.\", \"Sr\", \"III\", \"3rd\" — which is\n// not its last word either. The numerals are the generational ones only, so\n// a surname that reads as a numeral, \"Xi\" say, is kept.\nconst SUFFIX = /^(?:jr|sr|ii|iii|iv|\\d+(?:st|nd|rd|th))\\.?,?$/iu\n\n// Something said about the name rather than part of it, in brackets at its\n// end: \"(she/her)\", \"[away]\".\nconst TRAILING_ASIDE = /\\s*[([{][^)\\]}]*[)\\]}]\\s*$/u\n\nconst segmenters = new Map<string, Intl.Segmenter>()\n\nfunction graphemesOf(text: string, locale: string) {\n let segmenter = segmenters.get(locale)\n if (segmenter === undefined) {\n segmenter = new Intl.Segmenter(locale, { granularity: 'grapheme' })\n segmenters.set(locale, segmenter)\n }\n return Array.from(segmenter.segment(text), ({ segment }) => segment)\n}\n\n/**\n * The character that stands for `word`: its first grapheme that is a letter,\n * a number or a picture, or its first grapheme where it has none of those,\n * so something always shows. Upper-cased in the locale, and then one\n * grapheme of that, since upper-casing can lengthen it: \"ß\" is \"SS\".\n */\nfunction initialOf(word: string, locale: string) {\n const graphemes = graphemesOf(word, locale)\n const chosen =\n graphemes.find((grapheme) => INITIAL.test(grapheme)) ??\n graphemes.at(0) ??\n ''\n return graphemesOf(chosen.toLocaleUpperCase(locale), locale).at(0) ?? ''\n}\n\n/**\n * One letter, where a person takes two. A person has a first name and a last\n * name to initialise; a thing usually has neither, so the same rule applied\n * to \"Second Item\" would produce \"SI\" — a pair of initials for something that\n * was never two words in that sense.\n */\nfunction initialOfThing(name: string, locale: string) {\n return initialOf(name.trim(), locale)\n}\n\n/**\n * The initials of the first and the last word, which handles both \"Ada\" and\n * \"Ada Lovelace\" without a separate prop for how many to take. What a\n * display name carries around the name itself is left out first: a title\n * before it, a generational suffix after it, and an aside in brackets at its\n * end. A name written without spaces between its words — Japanese, Chinese —\n * is one word to this, and takes one initial.\n */\nfunction initialsOfPerson(name: string, locale: string) {\n let words = name.replace(TRAILING_ASIDE, '').split(/\\s+/u).filter(Boolean)\n if (words.length > 1 && TITLE.test(words[0] ?? '')) {\n words = words.slice(1)\n }\n if (words.length > 1 && SUFFIX.test(words.at(-1) ?? '')) {\n words = words.slice(0, -1)\n }\n if (words.length === 0) {\n return ''\n }\n const first = initialOf(words[0] ?? '', locale)\n if (words.length === 1) {\n return first\n }\n const last = initialOf(words.at(-1) ?? '', locale)\n const between =\n JOINING.test(first) && JOINING.test(last) ? ZERO_WIDTH_NON_JOINER : ''\n return `${first}${between}${last}`\n}\n\nexport { initialOfThing, initialsOfPerson }\n"],"mappings":";AAeA,MAAMA,UAAU;AAKhB,MAAMC,UACJ;AAEF,MAAMC,wBAAwB;AAI9B,MAAMC,QAAQ;AAKd,MAAMC,SAAS;AAIf,MAAMC,iBAAiB;AAEvB,MAAMC,6BAAa,IAAIC,IAA4B;AAEnD,SAASG,YAAYC,MAAcC,QAAgB;CACjD,IAAIC,YAAYP,WAAWQ,IAAIF,MAAM;CACrC,IAAIC,cAAcE,KAAAA,GAAW;EAC3BF,YAAY,IAAIL,KAAKC,UAAUG,QAAQ,EAAEI,aAAa,WAAW,CAAC;EAClEV,WAAWW,IAAIL,QAAQC,SAAS;CAClC;CACA,OAAOK,MAAMC,KAAKN,UAAUO,QAAQT,IAAI,IAAI,EAAES,cAAcA,OAAO;AACrE;;;;;;;AAQA,SAASC,UAAUC,MAAcV,QAAgB;CAC/C,MAAMW,YAAYb,YAAYY,MAAMV,MAAM;CAK1C,OAAOF,aAHLa,UAAUE,MAAMC,aAAa1B,QAAQ2B,KAAKD,QAAQ,CAAC,KACnDH,UAAUK,GAAG,CAAC,KACd,GAAA,CACwBC,kBAAkBjB,MAAM,GAAGA,MAAM,CAAC,CAACgB,GAAG,CAAC,KAAK;AACxE;;;;;;;AAQA,SAASE,eAAeC,MAAcnB,QAAgB;CACpD,OAAOS,UAAUU,KAAKC,KAAK,GAAGpB,MAAM;AACtC;;;;;;;;;AAUA,SAASqB,iBAAiBF,MAAcnB,QAAgB;CACtD,IAAIsB,QAAQH,KAAKI,QAAQ9B,gBAAgB,EAAE,CAAC,CAAC+B,MAAM,MAAM,CAAC,CAACC,OAAOC,OAAO;CACzE,IAAIJ,MAAMK,SAAS,KAAKpC,MAAMwB,KAAKO,MAAM,MAAM,EAAE,GAC/CA,QAAQA,MAAMM,MAAM,CAAC;CAEvB,IAAIN,MAAMK,SAAS,KAAKnC,OAAOuB,KAAKO,MAAMN,GAAG,EAAE,KAAK,EAAE,GACpDM,QAAQA,MAAMM,MAAM,GAAG,EAAE;CAE3B,IAAIN,MAAMK,WAAW,GACnB,OAAO;CAET,MAAME,QAAQpB,UAAUa,MAAM,MAAM,IAAItB,MAAM;CAC9C,IAAIsB,MAAMK,WAAW,GACnB,OAAOE;CAET,MAAMC,OAAOrB,UAAUa,MAAMN,GAAG,EAAE,KAAK,IAAIhB,MAAM;CAGjD,OAAO,GAAG6B,QADRxC,QAAQ0B,KAAKc,KAAK,KAAKxC,QAAQ0B,KAAKe,IAAI,IAAIxC,wBAAwB,KAC1CwC;AAC9B"}
package/dist/styles.css CHANGED
@@ -633,6 +633,10 @@
633
633
  animation-name: x17cjob-B;
634
634
  }
635
635
 
636
+ .xz09zy6 {
637
+ animation-name: x17j028-B, x26nhu8-B;
638
+ }
639
+
636
640
  .x1sz9pa8 {
637
641
  animation-name: x18qdip-B, x1b9nlqo-B;
638
642
  }
@@ -661,10 +665,6 @@
661
665
  animation-name: x1pch1fy-B;
662
666
  }
663
667
 
664
- .x14p4i3i {
665
- animation-name: x1t81ys1-B, x26nhu8-B;
666
- }
667
-
668
668
  .xhpbw76 {
669
669
  animation-name: x1uknk9t-B;
670
670
  }
@@ -1265,6 +1265,10 @@
1265
1265
  box-shadow: inset 0 -2px 0 0 var(--x1cjupv7);
1266
1266
  }
1267
1267
 
1268
+ .x19irva8 {
1269
+ box-shadow: inset 0 0 0 1px var(--x12p1wyw);
1270
+ }
1271
+
1268
1272
  .xbd69nm {
1269
1273
  box-shadow: inset 0 0 0 1px var(--x7dbk6n);
1270
1274
  }
@@ -2776,6 +2780,10 @@
2776
2780
  box-shadow: inset 0 -2px 0 0 var(--x1cjupv7);
2777
2781
  }
2778
2782
 
2783
+ .x1bll8u6:focus-within {
2784
+ box-shadow: inset 0 0 0 2px var(--x12p1wyw);
2785
+ }
2786
+
2779
2787
  .x19i8hm1:focus-within {
2780
2788
  box-shadow: inset 0 0 0 2px var(--x1cjupv7);
2781
2789
  }
@@ -4718,6 +4726,10 @@
4718
4726
  content: "";
4719
4727
  }
4720
4728
 
4729
+ .xvss7es:before {
4730
+ content: attr(data-count);
4731
+ }
4732
+
4721
4733
  .x1hcrkkg::-webkit-search-cancel-button {
4722
4734
  display: none;
4723
4735
  }
@@ -4991,17 +5003,17 @@
4991
5003
  }
4992
5004
  }
4993
5005
 
4994
- @keyframes x1t81ys1-B {
5006
+ @keyframes x17j028-B {
4995
5007
  0% {
4996
- stroke-dasharray: 8 100;
5008
+ stroke-dasharray: 8 92;
4997
5009
  }
4998
5010
 
4999
5011
  50% {
5000
- stroke-dasharray: 75 100;
5012
+ stroke-dasharray: 75 25;
5001
5013
  }
5002
5014
 
5003
5015
  100% {
5004
- stroke-dasharray: 8 100;
5016
+ stroke-dasharray: 8 92;
5005
5017
  }
5006
5018
  }
5007
5019
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kanso-labs/kanso-ui",
3
- "version": "0.40.8",
3
+ "version": "0.40.9",
4
4
  "description": "A React component library built on React Aria Components primitives and styled with StyleX, with design tokens sourced from a single W3C DTCG file and compiled via Style Dictionary",
5
5
  "keywords": [
6
6
  "react",