@loword/loword-design-system 0.2.1 → 0.2.3

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 (51) hide show
  1. package/dist/components/LDDataCalendar/LDDataCalendar.js +1 -1
  2. package/dist/components/LDDatePicker/LDDatePicker.js +1 -1
  3. package/dist/components/LDDateRangePicker/LDDateRangePicker.js +2 -2
  4. package/dist/components/LDEditor/EditorBase.d.ts.map +1 -1
  5. package/dist/components/LDEditor/EditorBase.js +25 -2
  6. package/dist/components/LDEditor/LDEditor.d.ts.map +1 -1
  7. package/dist/components/LDEditor/LDEditor.js +2 -1
  8. package/dist/components/LDFileUpload/FileUploadBase.d.ts +20 -4
  9. package/dist/components/LDFileUpload/FileUploadBase.d.ts.map +1 -1
  10. package/dist/components/LDFileUpload/FileUploadBase.js +41 -18
  11. package/dist/components/LDFileUpload/LDFileUpload.d.ts +19 -6
  12. package/dist/components/LDFileUpload/LDFileUpload.d.ts.map +1 -1
  13. package/dist/components/LDFileUpload/LDFileUpload.js +124 -28
  14. package/dist/components/LDFileUpload/LDFileUploadList.js +1 -1
  15. package/dist/components/LDInput/LDInput.d.ts +3 -1
  16. package/dist/components/LDInput/LDInput.d.ts.map +1 -1
  17. package/dist/components/LDInput/LDInput.js +10 -4
  18. package/dist/components/LDLNB/LDLNB.d.ts.map +1 -1
  19. package/dist/components/LDLNB/LDLNB.js +1 -2
  20. package/dist/components/LDLNB/LNBBase.d.ts +1 -2
  21. package/dist/components/LDLNB/LNBBase.d.ts.map +1 -1
  22. package/dist/components/LDLNB/LNBBase.js +10 -4
  23. package/dist/components/LDModal/LDModal.d.ts +7 -6
  24. package/dist/components/LDModal/LDModal.d.ts.map +1 -1
  25. package/dist/components/LDModal/LDModalView.d.ts +3 -3
  26. package/dist/components/LDModal/LDModalView.d.ts.map +1 -1
  27. package/dist/components/LDModal/LDModalView.js +6 -5
  28. package/dist/components/LDSelect/LDMultiSelect.js +1 -1
  29. package/dist/components/LDSelect/LDSelect.js +1 -1
  30. package/dist/components/LDTable/HeadlessTable.d.ts +4 -0
  31. package/dist/components/LDTable/HeadlessTable.d.ts.map +1 -1
  32. package/dist/components/LDTable/HeadlessTable.js +12 -1
  33. package/dist/components/LDTable/LDCollapsibleTanstackTable.d.ts.map +1 -1
  34. package/dist/components/LDTable/LDCollapsibleTanstackTable.js +2 -2
  35. package/dist/components/LDTable/LDTable.js +2 -2
  36. package/dist/components/LDTable/LDTanstackTable.d.ts.map +1 -1
  37. package/dist/components/LDTable/LDTanstackTable.js +2 -2
  38. package/dist/components/LDTextarea/LDTextarea.js +7 -7
  39. package/dist/components/LDTimePicker/LDTimePicker.js +1 -1
  40. package/dist/index.css +231 -21
  41. package/dist/index.d.ts +2 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +0 -1
  44. package/dist/utils/file.d.ts +2 -0
  45. package/dist/utils/file.d.ts.map +1 -1
  46. package/dist/utils/file.js +1 -0
  47. package/dist/utils/utils.d.ts +29 -3
  48. package/dist/utils/utils.d.ts.map +1 -1
  49. package/dist/utils/utils.js +93 -4
  50. package/package.json +1 -1
  51. package/src/styles/components/editor.css +14 -0
@@ -1,10 +1,99 @@
1
1
  /**
2
- * 현재 경로가 해당 링크의 경로와 **정확히** 일치하는지 판별합니다.
2
+ * URL 파싱용 더미 origin. `new URL()`에 base 를 주면 상대 경로·`..` 해석과
3
+ * 쿼리스트링·해시 분리를 표준 파서가 대신 처리한다.
4
+ */
5
+ const PARSE_BASE = 'http://ld.local';
6
+ /**
7
+ * 퍼센트 인코딩을 되돌립니다. `decodeURIComponent` 가 아니라 `decodeURI` 를 쓰는
8
+ * 이유는 `%2F` 같은 예약 문자까지 풀면 경로 구분자가 늘어나 세그먼트 경계가
9
+ * 어긋나기 때문입니다. 잘못된 인코딩이면 원문 그대로 비교합니다.
10
+ */
11
+ const safeDecode = (value) => {
12
+ try {
13
+ return decodeURI(value);
14
+ }
15
+ catch {
16
+ return value;
17
+ }
18
+ };
19
+ /**
20
+ * 비교 가능한 형태로 경로를 정규화합니다.
21
+ *
22
+ * - origin·쿼리스트링·해시 제거 (`https://a.com/foo?x=1#y` → `/foo`)
23
+ * - 상대 경로와 `.`·`..` 해석 (`foo/../bar` → `/bar`)
24
+ * - 중복 슬래시 축약 (`/foo//bar` → `/foo/bar`)
25
+ * - 끝 슬래시 제거 (루트 `/` 는 유지)
26
+ * - 퍼센트 인코딩 해제 (`/%EC%83%81%ED%92%88` → `/상품`)
27
+ *
28
+ * 대소문자는 구분합니다. 경로는 대소문자를 구분하는 것이 표준이고, 서로 다른
29
+ * 라우트를 같은 것으로 묶으면 오히려 오탐이 됩니다.
30
+ */
31
+ const toComparablePath = (value) => {
32
+ let pathname;
33
+ try {
34
+ ({ pathname } = new URL(value, PARSE_BASE));
35
+ }
36
+ catch {
37
+ // URL 로 해석되지 않는 문자열(예: 'http://')은 정규화 없이 원문을 쓴다.
38
+ return value;
39
+ }
40
+ const collapsed = safeDecode(pathname).replace(/\/{2,}/g, '/');
41
+ return collapsed.length > 1 && collapsed.endsWith('/')
42
+ ? collapsed.slice(0, -1)
43
+ : collapsed;
44
+ };
45
+ /**
46
+ * 현재 경로가 해당 링크의 경로에 속하는지 판별합니다.
47
+ *
48
+ * `href` 와 정확히 같거나 `href` 의 **하위 경로**면 활성으로 봅니다.
49
+ * `/products/items` 같은 상세 페이지에서도 상위 메뉴 `/products` 가 켜져 있어야
50
+ * 하기 때문입니다.
51
+ *
52
+ * 단순 `startsWith` 는 쓰지 않습니다. 세그먼트 경계(`/`)를 요구해서
53
+ * `/foo-bar` 가 `/foo` 에 걸리는 오탐을 막습니다. 루트(`/`)는 모든 경로의
54
+ * 접두사이므로 정확히 일치할 때만 활성입니다.
55
+ *
56
+ * 쿼리스트링과 해시는 비교하지 않습니다. `/search?q=A` 와 `/search?q=B` 는 같은
57
+ * 페이지이므로 검색어가 바뀌어도 메뉴가 꺼지면 안 됩니다. 반대로 `href` 를
58
+ * `/orders?status=done` 처럼 쿼리로 구분하는 메뉴는 서로 구별되지 않습니다.
59
+ *
60
+ * 주의: 항목 단위 판정이라 `/admin` 과 `/admin/group` 이 둘 다 메뉴에 있으면
61
+ * `/admin/group` 에서 두 항목이 함께 활성이 됩니다. 하나만 켜려면 호출부에서
62
+ * 가장 긴 매칭을 골라야 합니다.
63
+ */
64
+ export const isActivePath = (pathname, href) => {
65
+ const current = toComparablePath(pathname);
66
+ const target = toComparablePath(href);
67
+ if (target === '/')
68
+ return current === '/';
69
+ return current === target || current.startsWith(`${target}/`);
70
+ };
71
+ /**
72
+ * 후보 경로 목록 중 현재 경로에 **가장 구체적으로** 맞는 하나를 고릅니다.
73
+ * 맞는 것이 없으면 `null` 입니다.
3
74
  *
4
- * 접두사(prefix) 비교는 쓰지 않습니다. `startsWith`로 판별하면 `/admin`이
5
- * `/admin/group`·`/admin-group`까지 활성으로 잡아 여러 메뉴가 동시에 켜집니다.
75
+ * `isActivePath` 항목 단위 판정이라 `/admin` `/admin/group` 이 둘 다 후보면
76
+ * `/admin/group` 에서 항목이 함께 활성이 됩니다. 메뉴에서 하나만 켜려면
77
+ * 후보 전체를 보고 가장 긴 경로를 골라야 합니다.
78
+ *
79
+ * 정규화한 경로 길이로 비교하므로 `/foo` 와 `/foo/` 처럼 같은 경로를 가리키는
80
+ * 표기 차이는 우열을 만들지 않고, 동률이면 먼저 나온 후보를 씁니다.
81
+ * 반환값은 정규화 이전의 원본 문자열이라 호출부에서 `===` 로 항목을 찾을 수 있습니다.
6
82
  */
7
- export const isActivePath = (pathname, href) => pathname === href;
83
+ export const findActivePath = (pathname, candidates) => {
84
+ let matched = null;
85
+ let matchedLength = -1;
86
+ for (const candidate of candidates) {
87
+ if (!isActivePath(pathname, candidate))
88
+ continue;
89
+ const length = toComparablePath(candidate).length;
90
+ if (length > matchedLength) {
91
+ matched = candidate;
92
+ matchedLength = length;
93
+ }
94
+ }
95
+ return matched;
96
+ };
8
97
  /** 숫자를 정수로 내림 후 천 단위 콤마를 붙인 문자열로 변환합니다 (LDChart 툴팁 표시용). */
9
98
  export const formatNumberWithComma = (num = 0) => {
10
99
  if (isNaN(num)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loword/loword-design-system",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "로워드 디자인 시스템 컴포넌트 패키지(Tailwind v4)",
5
5
  "keywords": [
6
6
  "react",
@@ -30,6 +30,20 @@
30
30
  .prose :is(strong, b) {
31
31
  color: inherit !important;
32
32
  }
33
+
34
+ /* prose 기본값은 블록 요소에 상하 대칭 여백(my)을 준다. 문서 처음/끝에서는
35
+ 그 여백이 컨테이너 안쪽 빈 공간으로 보이므로 제거한다.
36
+ 기준을 .prose가 아니라 .ProseMirror로 잡는 이유: LDViewer는 prose를
37
+ EditorContent 래퍼에 주므로 본문 블록이 .prose의 손자가 된다.
38
+ 직계 자식(>)으로 한정하지 않는 이유: li > p, blockquote > p처럼 중첩된
39
+ 블록도 자기 부모의 처음/끝이면 같은 규칙이 적용돼야 한다. */
40
+ .ProseMirror :first-child {
41
+ margin-top: 0;
42
+ }
43
+
44
+ .ProseMirror :last-child {
45
+ margin-bottom: 0;
46
+ }
33
47
  }
34
48
 
35
49
  /* 이미지 정렬 스타일 */