@ncds/ui-admin 1.8.25 β 1.8.26-alpha.1
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/dist/cjs/assets/scripts/notification/FullWidthNotification.js +2 -0
- package/dist/cjs/assets/scripts/notification/MessageNotification.js +30 -23
- package/dist/cjs/assets/scripts/notification/const/classNames.js +3 -0
- package/dist/cjs/assets/scripts/notification/const/icons.js +11 -2
- package/dist/cjs/assets/scripts/notification/const/index.js +9 -4
- package/dist/cjs/assets/scripts/notification/const/sizes.js +6 -1
- package/dist/cjs/assets/scripts/notification/const/types.js +1 -10
- package/dist/cjs/assets/scripts/notification/messageTemplate.js +20 -8
- package/dist/cjs/assets/scripts/notification/utils.js +21 -17
- package/dist/cjs/constant/notification.js +15 -1
- package/dist/cjs/src/components/feedback-and-status/badge/Badge.js +1 -1
- package/dist/cjs/src/components/overlays/notification/FloatingNotification.js +4 -7
- package/dist/cjs/src/components/overlays/notification/FullWidthNotification.js +13 -8
- package/dist/cjs/src/components/overlays/notification/MessageNotification.js +20 -14
- package/dist/cjs/src/components/overlays/notification/MessageNotificationParts.js +22 -15
- package/dist/cjs/src/components/overlays/notification/Notification.js +6 -0
- package/dist/cjs/src/components/overlays/notification/NotificationActionButtons.js +27 -0
- package/dist/cjs/src/components/overlays/notification/__tests__/supportTextLink.test.js +58 -0
- package/dist/cjs/src/components/overlays/notification/linkTarget.js +18 -0
- package/dist/cjs/src/generated/scoped-css.js +1 -1
- package/dist/cjs/src/utils/index.js +11 -0
- package/dist/cjs/src/utils/url/__tests__/isSafeUrl.test.js +49 -0
- package/dist/cjs/src/utils/url/index.js +16 -0
- package/dist/cjs/src/utils/url/isSafeUrl.js +32 -0
- package/dist/esm/assets/scripts/notification/FullWidthNotification.js +3 -1
- package/dist/esm/assets/scripts/notification/MessageNotification.js +32 -25
- package/dist/esm/assets/scripts/notification/const/classNames.js +3 -0
- package/dist/esm/assets/scripts/notification/const/icons.js +10 -1
- package/dist/esm/assets/scripts/notification/const/index.js +2 -3
- package/dist/esm/assets/scripts/notification/const/sizes.js +5 -0
- package/dist/esm/assets/scripts/notification/const/types.js +1 -8
- package/dist/esm/assets/scripts/notification/messageTemplate.js +21 -9
- package/dist/esm/assets/scripts/notification/utils.js +19 -16
- package/dist/esm/constant/notification.js +14 -0
- package/dist/esm/src/components/feedback-and-status/badge/Badge.js +1 -1
- package/dist/esm/src/components/overlays/notification/FloatingNotification.js +4 -7
- package/dist/esm/src/components/overlays/notification/FullWidthNotification.js +13 -8
- package/dist/esm/src/components/overlays/notification/MessageNotification.js +21 -15
- package/dist/esm/src/components/overlays/notification/MessageNotificationParts.js +22 -15
- package/dist/esm/src/components/overlays/notification/Notification.js +6 -0
- package/dist/esm/src/components/overlays/notification/NotificationActionButtons.js +21 -0
- package/dist/esm/src/components/overlays/notification/__tests__/supportTextLink.test.js +55 -0
- package/dist/esm/src/components/overlays/notification/linkTarget.js +12 -0
- package/dist/esm/src/generated/scoped-css.js +1 -1
- package/dist/esm/src/utils/index.js +3 -1
- package/dist/esm/src/utils/url/__tests__/isSafeUrl.test.js +47 -0
- package/dist/esm/src/utils/url/index.js +1 -0
- package/dist/esm/src/utils/url/isSafeUrl.js +26 -0
- package/dist/temp/assets/scripts/notification/FullWidthNotification.js +3 -2
- package/dist/temp/assets/scripts/notification/MessageNotification.d.ts +2 -0
- package/dist/temp/assets/scripts/notification/MessageNotification.js +30 -25
- package/dist/temp/assets/scripts/notification/const/classNames.d.ts +3 -0
- package/dist/temp/assets/scripts/notification/const/classNames.js +3 -0
- package/dist/temp/assets/scripts/notification/const/icons.d.ts +6 -0
- package/dist/temp/assets/scripts/notification/const/icons.js +9 -0
- package/dist/temp/assets/scripts/notification/const/index.d.ts +3 -4
- package/dist/temp/assets/scripts/notification/const/index.js +2 -3
- package/dist/temp/assets/scripts/notification/const/sizes.d.ts +4 -0
- package/dist/temp/assets/scripts/notification/const/sizes.js +5 -0
- package/dist/temp/assets/scripts/notification/const/types.d.ts +28 -1
- package/dist/temp/assets/scripts/notification/const/types.js +1 -8
- package/dist/temp/assets/scripts/notification/messageTemplate.d.ts +5 -1
- package/dist/temp/assets/scripts/notification/messageTemplate.js +16 -11
- package/dist/temp/assets/scripts/notification/utils.d.ts +10 -3
- package/dist/temp/assets/scripts/notification/utils.js +21 -18
- package/dist/temp/constant/notification.d.ts +13 -0
- package/dist/temp/constant/notification.js +14 -0
- package/dist/temp/src/components/feedback-and-status/badge/Badge.d.ts +1 -1
- package/dist/temp/src/components/feedback-and-status/badge/Badge.js +1 -1
- package/dist/temp/src/components/overlays/notification/FloatingNotification.js +2 -2
- package/dist/temp/src/components/overlays/notification/FullWidthNotification.d.ts +6 -1
- package/dist/temp/src/components/overlays/notification/FullWidthNotification.js +7 -2
- package/dist/temp/src/components/overlays/notification/MessageNotification.d.ts +15 -1
- package/dist/temp/src/components/overlays/notification/MessageNotification.js +11 -12
- package/dist/temp/src/components/overlays/notification/MessageNotificationParts.d.ts +10 -5
- package/dist/temp/src/components/overlays/notification/MessageNotificationParts.js +9 -6
- package/dist/temp/src/components/overlays/notification/Notification.d.ts +23 -2
- package/dist/temp/src/components/overlays/notification/Notification.js +3 -3
- package/dist/temp/src/components/overlays/notification/NotificationActionButtons.d.ts +12 -0
- package/dist/temp/src/components/overlays/notification/NotificationActionButtons.js +9 -0
- package/dist/temp/src/components/overlays/notification/__tests__/supportTextLink.test.d.ts +1 -0
- package/dist/temp/src/components/overlays/notification/__tests__/supportTextLink.test.js +73 -0
- package/dist/temp/src/components/overlays/notification/linkTarget.d.ts +11 -0
- package/dist/temp/src/components/overlays/notification/linkTarget.js +9 -0
- package/dist/temp/src/generated/scoped-css.js +1 -1
- package/dist/temp/src/utils/index.d.ts +1 -0
- package/dist/temp/src/utils/index.js +2 -0
- package/dist/temp/src/utils/url/__tests__/isSafeUrl.test.d.ts +1 -0
- package/dist/temp/src/utils/url/__tests__/isSafeUrl.test.js +61 -0
- package/dist/temp/src/utils/url/index.d.ts +1 -0
- package/dist/temp/src/utils/url/index.js +1 -0
- package/dist/temp/src/utils/url/isSafeUrl.d.ts +8 -0
- package/dist/temp/src/utils/url/isSafeUrl.js +29 -0
- package/dist/types/assets/scripts/notification/MessageNotification.d.ts +2 -0
- package/dist/types/assets/scripts/notification/const/classNames.d.ts +3 -0
- package/dist/types/assets/scripts/notification/const/icons.d.ts +6 -0
- package/dist/types/assets/scripts/notification/const/index.d.ts +3 -4
- package/dist/types/assets/scripts/notification/const/sizes.d.ts +4 -0
- package/dist/types/assets/scripts/notification/const/types.d.ts +28 -1
- package/dist/types/assets/scripts/notification/messageTemplate.d.ts +5 -1
- package/dist/types/assets/scripts/notification/utils.d.ts +10 -3
- package/dist/types/constant/notification.d.ts +13 -0
- package/dist/types/src/components/feedback-and-status/badge/Badge.d.ts +1 -1
- package/dist/types/src/components/overlays/notification/FullWidthNotification.d.ts +6 -1
- package/dist/types/src/components/overlays/notification/MessageNotification.d.ts +15 -1
- package/dist/types/src/components/overlays/notification/MessageNotificationParts.d.ts +10 -5
- package/dist/types/src/components/overlays/notification/Notification.d.ts +23 -2
- package/dist/types/src/components/overlays/notification/NotificationActionButtons.d.ts +12 -0
- package/dist/types/src/components/overlays/notification/__tests__/supportTextLink.test.d.ts +1 -0
- package/dist/types/src/components/overlays/notification/linkTarget.d.ts +11 -0
- package/dist/types/src/utils/index.d.ts +1 -0
- package/dist/types/src/utils/url/__tests__/isSafeUrl.test.d.ts +1 -0
- package/dist/types/src/utils/url/index.d.ts +1 -0
- package/dist/types/src/utils/url/isSafeUrl.d.ts +8 -0
- package/dist/ui-admin/assets/styles/style.css +54 -34
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { isSafeUrl } from '../isSafeUrl';
|
|
3
|
+
/**
|
|
4
|
+
* μλ¦Ό ν
μ€νΈ λ§ν¬(`supportTextLink`)μ href νμ© μ¬λΆ.
|
|
5
|
+
* ReactΒ·Vanilla κ° μ΄ ν¨μ νλλ₯Ό 곡μ νλ€ (#538 리뷰 H2).
|
|
6
|
+
*
|
|
7
|
+
* μ΄ νμΌμ vitest κΈ°λ³Έ νκ²½(node)μμ λλ€ β `window` κ° μλ SSR μν© μμ²΄κ° κ²μ¦ λμμ΄λ€.
|
|
8
|
+
*/
|
|
9
|
+
const SAFE = [
|
|
10
|
+
'https://example.com/notice/1',
|
|
11
|
+
'http://example.com',
|
|
12
|
+
'HTTPS://EXAMPLE.COM',
|
|
13
|
+
'/notice/1',
|
|
14
|
+
'notice/1',
|
|
15
|
+
'../notice',
|
|
16
|
+
'?page=2',
|
|
17
|
+
'#section',
|
|
18
|
+
' https://example.com ',
|
|
19
|
+
];
|
|
20
|
+
const UNSAFE = [
|
|
21
|
+
'javascript:alert(1)',
|
|
22
|
+
'JavaScript:alert(1)',
|
|
23
|
+
' JavaScript:alert(1)',
|
|
24
|
+
'\tjavascript:alert(1)',
|
|
25
|
+
'java\nscript:alert(1)',
|
|
26
|
+
'data:text/html,<script>alert(1)</script>',
|
|
27
|
+
'DATA:text/html;base64,PHNjcmlwdD4=',
|
|
28
|
+
'vbscript:msgbox(1)',
|
|
29
|
+
'file:///etc/passwd',
|
|
30
|
+
'mailto:a@example.com',
|
|
31
|
+
'http://',
|
|
32
|
+
];
|
|
33
|
+
describe('isSafeUrl β window μμ(SSR)', () => {
|
|
34
|
+
it('window κ° μ μλμ§ μμ νκ²½μ΄λ€', () => {
|
|
35
|
+
expect(typeof window).toBe('undefined');
|
|
36
|
+
});
|
|
37
|
+
it.each(SAFE)('νμ©: %j', (url) => {
|
|
38
|
+
expect(isSafeUrl(url)).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
it.each(UNSAFE)('μ°¨λ¨: %j', (url) => {
|
|
41
|
+
expect(isSafeUrl(url)).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
it('λΉ λ¬Έμμ΄μ μ°¨λ¨νλ€', () => {
|
|
44
|
+
expect(isSafeUrl('')).toBe(false);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('isSafeUrl β window μ‘΄μ¬', () => {
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
vi.unstubAllGlobals();
|
|
50
|
+
});
|
|
51
|
+
it('νμ¬ origin κΈ°μ€μΌλ‘ μλκ²½λ‘λ₯Ό ν΄μν΄ νμ©νλ€', () => {
|
|
52
|
+
vi.stubGlobal('window', { location: { origin: 'https://admin.example.com' } });
|
|
53
|
+
expect(isSafeUrl('/notice/1')).toBe(true);
|
|
54
|
+
expect(isSafeUrl('javascript:alert(1)')).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it('origin μ΄ "null"(about:blankΒ·sandbox iframe)μ΄μ΄λ μλκ²½λ‘λ₯Ό νμ©νλ€', () => {
|
|
57
|
+
vi.stubGlobal('window', { location: { origin: 'null' } });
|
|
58
|
+
expect(isSafeUrl('/notice/1')).toBe(true);
|
|
59
|
+
expect(isSafeUrl(' JavaScript:alert(1)')).toBe(false);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './isSafeUrl';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './isSafeUrl';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* λ§ν¬ href λ‘ λ£μ΄λ μμ ν URL μΈμ§ νμ νλ€. http/https λ° μλκ²½λ‘λ§ νμ©νλ€.
|
|
3
|
+
* javascript:, data:, file: λ± μν νλ‘ν μ½λ‘ μΈν XSS / μΈλΆ νμ΄λ‘λ λ‘λ©μ μ°¨λ¨.
|
|
4
|
+
*
|
|
5
|
+
* URL νμκ° μλ€ κ³΅λ°±Β·νΒ·κ°ν μ κ±°μ scheme μλ¬Έμνλ₯Ό νλ―λ‘ ` JavaScript:` κ°μ μ°νλ λ§νλ€.
|
|
6
|
+
* React(`MessageNotificationParts`Β·`FullWidthNotification`)μ Vanilla(`renderSupportingText`)κ° κ³΅μ νλ€.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isSafeUrl(url: string): boolean;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* μλκ²½λ‘ ν΄μμ© κΈ°λ³Έ origin. `window` κ° μκ±°λ(SSR) origin μ΄ λΆν¬λͺ
(`"null"` β about:blank,
|
|
3
|
+
* sandbox iframe)μΌ λ μ΄λ€. νμ μ νλ‘ν μ½λ§ 보λ―λ‘ μ€μ νΈμ€νΈμ 무κ΄νλ€.
|
|
4
|
+
*/
|
|
5
|
+
const FALLBACK_ORIGIN = 'http://localhost';
|
|
6
|
+
function resolveBaseOrigin() {
|
|
7
|
+
if (typeof window === 'undefined')
|
|
8
|
+
return FALLBACK_ORIGIN;
|
|
9
|
+
const origin = window.location?.origin;
|
|
10
|
+
return origin && origin !== 'null' ? origin : FALLBACK_ORIGIN;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* λ§ν¬ href λ‘ λ£μ΄λ μμ ν URL μΈμ§ νμ νλ€. http/https λ° μλκ²½λ‘λ§ νμ©νλ€.
|
|
14
|
+
* javascript:, data:, file: λ± μν νλ‘ν μ½λ‘ μΈν XSS / μΈλΆ νμ΄λ‘λ λ‘λ©μ μ°¨λ¨.
|
|
15
|
+
*
|
|
16
|
+
* URL νμκ° μλ€ κ³΅λ°±Β·νΒ·κ°ν μ κ±°μ scheme μλ¬Έμνλ₯Ό νλ―λ‘ ` JavaScript:` κ°μ μ°νλ λ§νλ€.
|
|
17
|
+
* React(`MessageNotificationParts`Β·`FullWidthNotification`)μ Vanilla(`renderSupportingText`)κ° κ³΅μ νλ€.
|
|
18
|
+
*/
|
|
19
|
+
export function isSafeUrl(url) {
|
|
20
|
+
if (!url.trim())
|
|
21
|
+
return false;
|
|
22
|
+
try {
|
|
23
|
+
const parsed = new URL(url, resolveBaseOrigin());
|
|
24
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -9,6 +9,8 @@ export declare class MessageNotification {
|
|
|
9
9
|
private featuredIcon?;
|
|
10
10
|
constructor(options: MessageNotificationOptions);
|
|
11
11
|
private createElement;
|
|
12
|
+
/** μμλ³ FeaturedIcon. default λ md(40/20), block μ sm(32/16). */
|
|
13
|
+
private createFeaturedIcon;
|
|
12
14
|
private bindEvents;
|
|
13
15
|
private setupAutoClose;
|
|
14
16
|
getElement(): HTMLElement;
|
|
@@ -8,6 +8,7 @@ export declare const CLASS_NAMES: {
|
|
|
8
8
|
readonly TEXT_CONTAINER: "ncua-full-width-notification__text-container";
|
|
9
9
|
readonly TITLE: "ncua-full-width-notification__title";
|
|
10
10
|
readonly SUPPORTING_TEXT: "ncua-full-width-notification__supporting-text";
|
|
11
|
+
readonly LINK: "ncua-full-width-notification__link";
|
|
11
12
|
readonly ACTIONS_CONTAINER: "ncua-full-width-notification__actions-container";
|
|
12
13
|
readonly ACTIONS: "ncua-full-width-notification__actions";
|
|
13
14
|
readonly CLOSE_BUTTON: "ncua-full-width-notification__close-button";
|
|
@@ -25,6 +26,7 @@ export declare const CLASS_NAMES: {
|
|
|
25
26
|
};
|
|
26
27
|
readonly MESSAGE: {
|
|
27
28
|
readonly BASE: "ncua-message-notification";
|
|
29
|
+
readonly BLOCK: "ncua-message-notification--block";
|
|
28
30
|
readonly CONTAINER: "ncua-message-notification__container";
|
|
29
31
|
readonly CONTENT: "ncua-message-notification__content";
|
|
30
32
|
readonly CONTENT_WRAPPER: "ncua-message-notification__content-wrapper";
|
|
@@ -32,6 +34,7 @@ export declare const CLASS_NAMES: {
|
|
|
32
34
|
readonly TEXT_CONTAINER: "ncua-message-notification__text-container";
|
|
33
35
|
readonly TITLE: "ncua-message-notification__title";
|
|
34
36
|
readonly SUPPORTING_TEXT: "ncua-message-notification__supporting-text";
|
|
37
|
+
readonly LINK: "ncua-message-notification__link";
|
|
35
38
|
readonly ACTIONS_CONTAINER: "ncua-message-notification__actions-container";
|
|
36
39
|
readonly ACTIONS: "ncua-message-notification__actions";
|
|
37
40
|
readonly FOOTER_CONTAINER: "ncua-message-notification__footer-container";
|
|
@@ -23,3 +23,9 @@ export declare const ICON_MAP: {
|
|
|
23
23
|
readonly success: (size: string) => string;
|
|
24
24
|
readonly info: (size: string) => string;
|
|
25
25
|
};
|
|
26
|
+
/**
|
|
27
|
+
* message νμ
μμ΄μ½. floating κ³Ό κ°μ 4μμ block λ³ν μ μ© info λ₯Ό λνλ€.
|
|
28
|
+
* `SVG_ICONS['info-circle']`μ full-width μ μ© classΒ·color κ° λ°ν μμ΄ μ°μ§ μλλ€
|
|
29
|
+
* (`.ncua-full-width-notification__icon`μ λͺ¨λ°μΌμμ μ¨κ²¨μ§λ€).
|
|
30
|
+
*/
|
|
31
|
+
export declare const MESSAGE_ICON_MAP: Partial<Record<NotificationColor, (size: string) => string>>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { CLASS_NAMES } from './classNames';
|
|
2
|
-
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, SVG_ICONS } from './icons';
|
|
3
|
-
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES, MESSAGE_SIZES, } from './sizes';
|
|
4
|
-
export type { BaseNotificationOptions, LegacyNotificationHierarchy, NotificationAction, NotificationActionButtonSize, NotificationColor, NotificationHierarchy, } from './types';
|
|
5
|
-
export { MESSAGE_CLOSE_ICON_COLORS } from './types';
|
|
2
|
+
export { FLOATING_ICON_MAP, FULL_WIDTH_ICON_MAP, ICON_MAP, MESSAGE_ICON_MAP, SVG_ICONS } from './icons';
|
|
3
|
+
export { CLOSE_BUTTON_SIZES, CLOSE_BUTTON_SVG_SIZES, FEATURED_ICON_SIZES, FULL_WIDTH_SIZES, getSizes, ICON_PIXEL_SIZES, MESSAGE_BLOCK_SIZES, MESSAGE_SIZES, } from './sizes';
|
|
4
|
+
export type { BaseNotificationOptions, LegacyNotificationHierarchy, NotificationAction, NotificationActionButtonSize, NotificationColor, NotificationHierarchy, NotificationLinkTarget, NotificationVariant, } from './types';
|
|
@@ -24,6 +24,10 @@ export declare const MESSAGE_SIZES: {
|
|
|
24
24
|
readonly ICON_PIXEL: "20";
|
|
25
25
|
readonly CLOSE_BUTTON: "20";
|
|
26
26
|
};
|
|
27
|
+
export declare const MESSAGE_BLOCK_SIZES: {
|
|
28
|
+
readonly FEATURED_ICON: "sm";
|
|
29
|
+
readonly ICON_PIXEL: "16";
|
|
30
|
+
};
|
|
27
31
|
export declare const getSizes: {
|
|
28
32
|
readonly featuredIcon: (isMobile: boolean) => "sm" | "md";
|
|
29
33
|
readonly iconPixel: (isMobile: boolean) => "20" | "16";
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
export type NotificationColor = 'neutral' | 'error' | 'warning' | 'success' | 'info';
|
|
2
|
+
/**
|
|
3
|
+
* message νμ
μ νμ λ³ν. React `NotificationVariant`μ κ°μ μ΄νλ€.
|
|
4
|
+
* - `'default'`: κΈ°μ‘΄ message
|
|
5
|
+
* - `'block'`: μλΈ νμ΄μ§ 곡μ§μ© (ν° λ°°κ²½, FeaturedIcon sm, μ λͺ© + ν
μ€νΈ λ§ν¬ 1ν, info μ μ§)
|
|
6
|
+
*/
|
|
7
|
+
export type NotificationVariant = 'default' | 'block';
|
|
8
|
+
/**
|
|
9
|
+
* ν
μ€νΈ λ§ν¬(`supportTextLink`)λ₯Ό μ¬λ λμ. React `NotificationLinkTarget`κ³Ό κ°μ μ΄νλ€.
|
|
10
|
+
* - `'_self'`: κ°μ ν (targetΒ·rel λ―ΈλΆμ¬)
|
|
11
|
+
* - `'_blank'`: μ ν (`target="_blank"` + `rel="noopener noreferrer"`)
|
|
12
|
+
*/
|
|
13
|
+
export type NotificationLinkTarget = '_self' | '_blank';
|
|
2
14
|
/**
|
|
3
15
|
* μλ¦Ό μ‘μ
λ²νΌ(`ncua-btn`)μ μμ μμμ.
|
|
4
16
|
* React `NotificationAction.hierarchy`μ λμΌν μ΄νλ₯Ό μ΄λ€ β `ButtonTheme`μ λΆλΆμ§ν©μ΄λ€.
|
|
@@ -31,7 +43,23 @@ export interface BaseNotificationOptions {
|
|
|
31
43
|
className?: string;
|
|
32
44
|
actions?: NotificationAction[];
|
|
33
45
|
autoClose?: number;
|
|
46
|
+
/**
|
|
47
|
+
* supportingTextμ λν λ§ν¬ URL. full-width νμ
, message νμ
μ `variant: 'block'`μμ μ¬μ© κ°λ₯.
|
|
48
|
+
* http/https λ§ νμ©λλ©° κ·Έ μΈ νλ‘ν μ½μ λ§ν¬ μμ΄ ν
μ€νΈλ§ λ λλλ€.
|
|
49
|
+
*/
|
|
34
50
|
supportTextLink?: string;
|
|
51
|
+
/**
|
|
52
|
+
* ν
μ€νΈ λ§ν¬λ₯Ό μ¬λ λμ. `supportTextLink`κ° λ λλ λλ§ λμνλ€.
|
|
53
|
+
* `'_blank'`μ΄λ©΄ μ νμΌλ‘ μ΄κ³ `rel="noopener noreferrer"`λ₯Ό ν¨κ» λΆμΈλ€.
|
|
54
|
+
* `'_blank'`κ° μλ κ°μ λͺ¨λ `'_self'`(κ°μ ν)λ‘ μ·¨κΈνλ€.
|
|
55
|
+
* @default '_self'
|
|
56
|
+
*/
|
|
57
|
+
supportTextLinkTarget?: NotificationLinkTarget;
|
|
58
|
+
/**
|
|
59
|
+
* message νμ
μ νμ λ³ν. message νμ
μμλ§ λμνλ€.
|
|
60
|
+
* @default 'default'
|
|
61
|
+
*/
|
|
62
|
+
variant?: NotificationVariant;
|
|
35
63
|
onHidePermanently?: () => void;
|
|
36
64
|
/**
|
|
37
65
|
* λ€μλ³΄μ§ μκΈ° λ²νΌμ λΌλ²¨. full-width, message νμ
μμ μ¬μ© κ°λ₯νλ©°
|
|
@@ -44,4 +72,3 @@ export interface BaseNotificationOptions {
|
|
|
44
72
|
*/
|
|
45
73
|
hidePermanentlyLabel?: string;
|
|
46
74
|
}
|
|
47
|
-
export declare const MESSAGE_CLOSE_ICON_COLORS: Record<NotificationColor, string>;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import type { NotificationAction } from './const';
|
|
1
|
+
import type { NotificationAction, NotificationColor } from './const';
|
|
2
2
|
export interface MessageTemplateParams {
|
|
3
3
|
title: string;
|
|
4
4
|
supportingText?: string;
|
|
5
|
+
/** μ§μ μ `supportingText`λ₯Ό ν
μ€νΈ λ§ν¬λ‘ λ λνλ€ (block λ³ν μ μ©, http/https λ§ νμ©). */
|
|
6
|
+
supportTextLink?: string;
|
|
7
|
+
/** λ«κΈ° μμ΄μ½ μ κ²°μ μ©. λ―Έμ§μ μ neutral. */
|
|
8
|
+
color?: NotificationColor;
|
|
5
9
|
actions?: NotificationAction[];
|
|
6
10
|
onClose?: () => void;
|
|
7
11
|
onHidePermanently?: () => void;
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { LegacyNotificationHierarchy, NotificationAction, NotificationActionButtonSize, NotificationColor, NotificationHierarchy } from './const';
|
|
2
2
|
export declare function createWrapperElement(baseClass: string, color: NotificationColor, className?: string): HTMLElement;
|
|
3
3
|
export declare function buildClassName(baseClass: string, color: NotificationColor, className?: string): string;
|
|
4
|
-
export declare function renderSupportingText(supportingText?: string, className?: string, supportTextLink?: string): string;
|
|
4
|
+
export declare function renderSupportingText(supportingText?: string, className?: string, supportTextLink?: string, linkClassName?: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* `supportTextLinkTarget`μ΄ `'_blank'`μ΄λ©΄ `renderSupportingText`κ° λ§λ λ§ν¬λ₯Ό μ νμΌλ‘ μ°λ€.
|
|
7
|
+
*
|
|
8
|
+
* target μ sanitize **μ΄ν** μ°λ¦¬κ° λ§λ λ§ν¬(ν
μ€νΈ 컨ν
μ΄λμ μ§κ³ `<a>`)μλ§ μ§μ νλ€.
|
|
9
|
+
* DOMPurify μ target μ μ μ νμ©νλ©΄ μ¬μ©μ μ
λ ₯ HTML μ `<a target>`κΉμ§ rel μμ΄ ν΅κ³ΌνκΈ° λλ¬Έμ΄λ€.
|
|
10
|
+
* λ°νμ μ
λ ₯μ΄λ―λ‘ `'_blank'`κ° μλ κ°μ μ λΆ `'_self'`(μμ± λ―ΈλΆμ¬)λ‘ μ·¨κΈνλ€.
|
|
11
|
+
*/
|
|
12
|
+
export declare function applySupportTextLinkTarget(root: HTMLElement, textContainerClassName: string, linkClassName: string, target: unknown): void;
|
|
5
13
|
/**
|
|
6
14
|
* μ‘μ
λ²νΌμ μμ μμμλ₯Ό νν μ΄νλ‘ μ κ·ννλ€.
|
|
7
15
|
*
|
|
@@ -16,8 +24,7 @@ export declare function resolveActionHierarchy(hierarchy?: NotificationHierarchy
|
|
|
16
24
|
/**
|
|
17
25
|
* μ‘μ
λ²νΌ κ·Έλ£Ή HTMLμ λ§λ λ€.
|
|
18
26
|
*
|
|
19
|
-
* `size` κΈ°λ³Έκ° '
|
|
20
|
-
* message νμ
λ§ TO-BE κ·κ²©(28px)μ λ§μΆ° 'xs'λ₯Ό λκΈ΄λ€ β React `<Button size="xs">`μ λμΌ.
|
|
27
|
+
* `size` κΈ°λ³Έκ° 'xs'λ λμμΈ κΈ°μ€(#535 β λͺ¨λ type μ‘μ
λ²νΌ xs)μ΄λ©° React `<Button size="xs">`μ κ°λ€.
|
|
21
28
|
*/
|
|
22
29
|
export declare function renderActions(actions: NotificationAction[], wrapperClass: string, size?: NotificationActionButtonSize): string;
|
|
23
30
|
export declare function bindNotificationEvents(element: HTMLElement, actions: NotificationAction[], onClose?: () => void, onRemove?: () => void): void;
|
|
@@ -13,3 +13,16 @@ export declare const HIDE_PERMANENTLY_LABEL: {
|
|
|
13
13
|
readonly message: "λ€μ λ³΄μ§ μκΈ°";
|
|
14
14
|
readonly fullWidth: "λ€μλ³΄μ§ μκΈ°";
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* message νμ
λ«κΈ°(X) μμ΄μ½μ color λ³ μ.
|
|
18
|
+
*
|
|
19
|
+
* React(`MessageNotification.tsx`)μ Vanilla(`messageTemplate.ts`)κ° ν¨κ» μ°Έμ‘°νλ λ¨μΌ μΆμ²λ€.
|
|
20
|
+
* `info`λ `variant: 'block'`μμλ§ λ λλλ€(default λ neutral λ‘ ν΄λ°±).
|
|
21
|
+
*/
|
|
22
|
+
export declare const MESSAGE_CLOSE_ICON_COLOR: {
|
|
23
|
+
readonly neutral: string;
|
|
24
|
+
readonly error: string;
|
|
25
|
+
readonly warning: string;
|
|
26
|
+
readonly success: string;
|
|
27
|
+
readonly info: string;
|
|
28
|
+
};
|
|
@@ -16,4 +16,4 @@ type BadgeProps = {
|
|
|
16
16
|
};
|
|
17
17
|
declare const Badge: ({ label, type, color, className, leadingIcon, trailingIcon, size, }: BadgeProps) => import("react/jsx-runtime").JSX.Element;
|
|
18
18
|
export { Badge };
|
|
19
|
-
export type {
|
|
19
|
+
export type { BadgeColor, BadgeProps, BadgeSize, BadgeType };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
|
|
2
|
-
import type { NotificationAction, NotificationColor } from './Notification';
|
|
2
|
+
import type { NotificationAction, NotificationColor, NotificationLinkTarget } from './Notification';
|
|
3
3
|
interface FullWidthNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title'> {
|
|
4
4
|
/**
|
|
5
5
|
* μλ¦Ό μ λͺ© ν
μ€νΈ
|
|
@@ -36,6 +36,11 @@ interface FullWidthNotificationProps extends Omit<ComponentPropsWithoutRef<'div'
|
|
|
36
36
|
* info λ§ν¬ μμ (μ νμ¬ν)
|
|
37
37
|
*/
|
|
38
38
|
supportTextLink?: string;
|
|
39
|
+
/**
|
|
40
|
+
* ν
μ€νΈ λ§ν¬λ₯Ό μ¬λ λμ (μ νμ¬ν). `'_blank'`μ΄λ©΄ μ ν + `rel="noopener noreferrer"`
|
|
41
|
+
* @default '_self'
|
|
42
|
+
*/
|
|
43
|
+
supportTextLinkTarget?: NotificationLinkTarget;
|
|
39
44
|
/**
|
|
40
45
|
* λ€μλ³΄μ§ μκΈ° μ΄λ²€νΈ νΈλ€λ¬ (μ νμ¬ν)
|
|
41
46
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
|
|
2
2
|
import type { SlotIconComponent } from '../../../types/side-slot';
|
|
3
|
-
import type { NotificationAction, NotificationColor } from './Notification';
|
|
3
|
+
import type { NotificationAction, NotificationColor, NotificationLinkTarget, NotificationVariant } from './Notification';
|
|
4
4
|
interface MessageNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title'> {
|
|
5
5
|
/**
|
|
6
6
|
* μλ¦Ό μ λͺ© ν
μ€νΈ
|
|
@@ -41,6 +41,20 @@ interface MessageNotificationProps extends Omit<ComponentPropsWithoutRef<'div'>,
|
|
|
41
41
|
* @default 'λ€μ λ³΄μ§ μκΈ°'
|
|
42
42
|
*/
|
|
43
43
|
hidePermanentlyLabel?: ReactNode;
|
|
44
|
+
/**
|
|
45
|
+
* νμ λ³ν. `'block'`μ μλΈ νμ΄μ§ 곡μ§μ©(ν° λ°°κ²½, FeaturedIcon sm, μ λͺ© + ν
μ€νΈ λ§ν¬ 1ν, info μ μ§)
|
|
46
|
+
* @default 'default'
|
|
47
|
+
*/
|
|
48
|
+
variant?: NotificationVariant;
|
|
49
|
+
/**
|
|
50
|
+
* ν
μ€νΈ λ§ν¬ URL. `variant="block"`μμλ§ λμνλ©° `supportingText`κ° λ§ν¬ ν
μ€νΈκ° λλ€.
|
|
51
|
+
*/
|
|
52
|
+
supportTextLink?: string;
|
|
53
|
+
/**
|
|
54
|
+
* ν
μ€νΈ λ§ν¬λ₯Ό μ¬λ λμ. `'_blank'`μ΄λ©΄ μ ν + `rel="noopener noreferrer"`
|
|
55
|
+
* @default '_self'
|
|
56
|
+
*/
|
|
57
|
+
supportTextLinkTarget?: NotificationLinkTarget;
|
|
44
58
|
}
|
|
45
59
|
declare const MessageNotification: import("react").ForwardRefExoticComponent<MessageNotificationProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
46
60
|
export type { MessageNotificationProps };
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import type { SlotIconComponent } from '../../../types/side-slot';
|
|
3
|
-
import { type FeaturedIconColor } from '../../image-and-icons/featured-icon/FeaturedIcon';
|
|
4
|
-
import type { NotificationAction } from './Notification';
|
|
3
|
+
import { type FeaturedIconColor, type FeaturedIconSize } from '../../image-and-icons/featured-icon/FeaturedIcon';
|
|
4
|
+
import type { NotificationAction, NotificationLinkTarget } from './Notification';
|
|
5
5
|
interface MessageNotificationContentProps {
|
|
6
6
|
title: ReactNode;
|
|
7
7
|
supportingText?: ReactNode;
|
|
8
|
+
/** μ§μ μ `supportingText`λ₯Ό μ΄ URL μ ν
μ€νΈ λ§ν¬λ‘ λ λνλ€ (block λ³ν μ μ©). http/httpsΒ·μλκ²½λ‘κ° μλλ©΄ ν
μ€νΈλ§ λ λ. */
|
|
9
|
+
supportTextLink?: string;
|
|
10
|
+
/** ν
μ€νΈ λ§ν¬λ₯Ό μ¬λ λμ. `'_blank'`μ΄λ©΄ μ ν + `rel="noopener noreferrer"`. */
|
|
11
|
+
supportTextLinkTarget?: NotificationLinkTarget;
|
|
8
12
|
icon?: SlotIconComponent;
|
|
9
13
|
iconColor: FeaturedIconColor;
|
|
10
|
-
|
|
14
|
+
/** default λ md(40/20), block μ sm(32/16). */
|
|
15
|
+
iconSize: FeaturedIconSize;
|
|
11
16
|
}
|
|
12
|
-
/** μμ΄μ½ + μ λͺ©/μν¬ν
ν
μ€νΈ μμ. */
|
|
13
|
-
declare const MessageNotificationContent: ({ title, supportingText, icon, iconColor,
|
|
17
|
+
/** μμ΄μ½ + μ λͺ©/μν¬ν
ν
μ€νΈ(λλ ν
μ€νΈ λ§ν¬) μμ. */
|
|
18
|
+
declare const MessageNotificationContent: ({ title, supportingText, supportTextLink, supportTextLinkTarget, icon, iconColor, iconSize, }: MessageNotificationContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
14
19
|
interface MessageNotificationActionsProps {
|
|
15
20
|
actions?: NotificationAction[];
|
|
16
21
|
onClose?: () => void;
|
|
@@ -6,6 +6,9 @@ import { type CalloutNotificationProps, type CalloutNotificationWidth } from './
|
|
|
6
6
|
type NotificationType = 'floating' | 'full-width' | 'message' | 'callout';
|
|
7
7
|
type NotificationColor = Extract<ColorTone, 'neutral' | 'error' | 'warning' | 'success' | 'info'>;
|
|
8
8
|
type NotificationSize = 'desktop' | 'mobile';
|
|
9
|
+
type NotificationVariant = 'default' | 'block';
|
|
10
|
+
/** ν
μ€νΈ λ§ν¬(`supportTextLink`)λ₯Ό μ¬λ λμ. `'_blank'`μ΄λ©΄ μ ν + `rel="noopener noreferrer"`. */
|
|
11
|
+
type NotificationLinkTarget = '_self' | '_blank';
|
|
9
12
|
interface NotificationAction {
|
|
10
13
|
/**
|
|
11
14
|
* μ‘μ
λ²νΌ ν
μ€νΈ
|
|
@@ -78,9 +81,27 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
78
81
|
hidePermanentlyLabel?: ReactNode;
|
|
79
82
|
/**
|
|
80
83
|
* supportingText μ μ°κ²°ν λ§ν¬ URL (μ νμ¬ν)
|
|
81
|
-
* full-width
|
|
84
|
+
* full-width νμ
, message νμ
μ `variant="block"`μμ μ¬μ© κ°λ₯
|
|
82
85
|
*/
|
|
83
86
|
supportTextLink?: string;
|
|
87
|
+
/**
|
|
88
|
+
* ν
μ€νΈ λ§ν¬λ₯Ό μ¬λ λμ (μ νμ¬ν). `supportTextLink`κ° λ λλ λλ§ λμνλ€.
|
|
89
|
+
* `'_blank'`μ΄λ©΄ μ νμΌλ‘ μ΄κ³ `rel="noopener noreferrer"`λ₯Ό ν¨κ» λΆμΈλ€.
|
|
90
|
+
* full-width νμ
, message νμ
μ `variant="block"`μμ μ¬μ© κ°λ₯
|
|
91
|
+
* @default '_self'
|
|
92
|
+
*/
|
|
93
|
+
supportTextLinkTarget?: NotificationLinkTarget;
|
|
94
|
+
/**
|
|
95
|
+
* message νμ
μ νμ λ³ν (μ νμ¬ν). message νμ
μμλ§ λμνλ€.
|
|
96
|
+
*
|
|
97
|
+
* - `'default'`: κΈ°μ‘΄ message (color λ³ λ°°κ²½Β·ν
λ리, μ λͺ© + λ³Έλ¬Έ 2ν, info β neutral ν΄λ°±)
|
|
98
|
+
* - `'block'`: μλΈ νμ΄μ§ 곡μ§μ©. ν° λ°°κ²½Β·gray-100 ν
λ리·shadow-sm, FeaturedIcon sm,
|
|
99
|
+
* μ λͺ© + ν
μ€νΈ λ§ν¬ 1ν(`supportingText` κ° λ§ν¬ ν
μ€νΈ, `supportTextLink` κ° href).
|
|
100
|
+
* `color="info"` λ₯Ό κ·Έλλ‘ λ λνλ€.
|
|
101
|
+
*
|
|
102
|
+
* @default 'default'
|
|
103
|
+
*/
|
|
104
|
+
variant?: NotificationVariant;
|
|
84
105
|
/**
|
|
85
106
|
* λλΉ λμ (μ νμ¬ν)
|
|
86
107
|
* callout νμ
μμλ§ μ¬μ© κ°λ₯. λ―Έμ§μ μ λΆλͺ¨ λλΉλ₯Ό μ±μ΄λ€(100%). 'fit' μ μ½ν
μΈ λλΉμ λ§μΆλ€
|
|
@@ -101,6 +122,6 @@ interface NotificationProps extends Omit<ComponentPropsWithoutRef<'div'>, 'title
|
|
|
101
122
|
portal?: boolean;
|
|
102
123
|
}
|
|
103
124
|
declare const Notification: import("react").ForwardRefExoticComponent<NotificationProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
104
|
-
export type { NotificationType, NotificationColor, NotificationSize, NotificationAction, NotificationProps };
|
|
125
|
+
export type { NotificationType, NotificationColor, NotificationSize, NotificationVariant, NotificationLinkTarget, NotificationAction, NotificationProps, };
|
|
105
126
|
export type { CalloutNotificationProps, CalloutNotificationWidth };
|
|
106
127
|
export { Notification };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { NotificationAction } from './Notification';
|
|
2
|
+
interface NotificationActionButtonsProps {
|
|
3
|
+
actions: NotificationAction[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* μλ¦Ό μ‘μ
λ²νΌ λͺ©λ‘. λͺ¨λ type μ΄ κ°μ κ·κ²©(`ncua-btn--xs` + hierarchy, κΈ°λ³Έ `text`)μ μ΄λ€(#535).
|
|
7
|
+
* Vanilla `renderActions`(assets/scripts/notification/utils.ts)μ κ°μ ν΄λμ€λ₯Ό μ°μΆν΄μΌ νλ€.
|
|
8
|
+
* κ°μΈλ λνΌ(`__actions`)λ type λ§λ€ ν΄λμ€κ° λ¬λΌ νΈμΆλΆκ° λ΄λΉνλ€.
|
|
9
|
+
*/
|
|
10
|
+
declare const NotificationActionButtons: ({ actions }: NotificationActionButtonsProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export type { NotificationActionButtonsProps };
|
|
12
|
+
export { NotificationActionButtons };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { NotificationLinkTarget } from './Notification';
|
|
2
|
+
/**
|
|
3
|
+
* ν
μ€νΈ λ§ν¬(`supportTextLink`)μ `<a>`μ λΆμΌ targetΒ·rel μμ±.
|
|
4
|
+
*
|
|
5
|
+
* `'_blank'`μΌ λλ§ μ ν + `rel="noopener noreferrer"`λ₯Ό λ°ννκ³ , `'_self'`(κΈ°λ³Έ)λ μ무 μμ±λ λΆμ΄μ§ μλλ€.
|
|
6
|
+
* Vanilla `applySupportTextLinkTarget`κ³Ό κ°μ λ§ν¬μ
μ μ°μΆν΄μΌ νλ€.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getLinkTargetAttributes(target?: NotificationLinkTarget): {
|
|
9
|
+
readonly target: "_blank";
|
|
10
|
+
readonly rel: "noopener noreferrer";
|
|
11
|
+
} | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './isSafeUrl';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* λ§ν¬ href λ‘ λ£μ΄λ μμ ν URL μΈμ§ νμ νλ€. http/https λ° μλκ²½λ‘λ§ νμ©νλ€.
|
|
3
|
+
* javascript:, data:, file: λ± μν νλ‘ν μ½λ‘ μΈν XSS / μΈλΆ νμ΄λ‘λ λ‘λ©μ μ°¨λ¨.
|
|
4
|
+
*
|
|
5
|
+
* URL νμκ° μλ€ κ³΅λ°±Β·νΒ·κ°ν μ κ±°μ scheme μλ¬Έμνλ₯Ό νλ―λ‘ ` JavaScript:` κ°μ μ°νλ λ§νλ€.
|
|
6
|
+
* React(`MessageNotificationParts`Β·`FullWidthNotification`)μ Vanilla(`renderSupportingText`)κ° κ³΅μ νλ€.
|
|
7
|
+
*/
|
|
8
|
+
export declare function isSafeUrl(url: string): boolean;
|