@charcoal-ui/icons 3.13.0 → 3.14.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.
- package/dist/PixivIcon.d.ts.map +1 -1
- package/dist/charcoalIconFiles.d.ts +1 -1
- package/dist/charcoalIconFiles.d.ts.map +1 -1
- package/dist/index.cjs.js +3 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +3 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/loaders/CharcoalIconFilesLoader.d.ts +1 -1
- package/dist/loaders/CharcoalIconFilesLoader.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/CustomIcon.mdx +38 -0
- package/src/PixivIcon.test.tsx +2 -1
- package/src/PixivIcon.ts +5 -2
- package/src/README.mdx +92 -0
- package/src/SSR.mdx +63 -0
package/dist/PixivIcon.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PixivIcon.d.ts","sourceRoot":"","sources":["../src/PixivIcon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AASnD,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC;CAAG;AAExE,MAAM,WAAW,KACf,SAAQ,IAAI,CACV,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,EACvE,WAAW,GAAG,KAAK,CACpB;IACD,IAAI,EAAE,MAAM,aAAa,CAAA;IACzB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACnC,4BAA4B,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAI9C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,KAAK,gBAAgB,GAAG,OAAO,CAAC,MAAM,aAAa,EAAE,aAAa,CAAC,CAAA;AACnE,KAAK,QAAQ,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,GAC9C,KAAK,GACL,IAAI,CAAA;AAER,qBAAa,SAAU,SAAQ,WAAW;IACxC,MAAM,CAAC,QAAQ,CAAC,OAAO,gBAAe;IAEtC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,QAAQ,SAAS,IAAI,GACtB,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkB5B,MAAM,KAAK,kBAAkB,6DAE5B;IAED,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAsB;IACvC,OAAO,CAAC,SAAS,CAAQ;IAEzB,IAAI,KAAK;;;;MAqBR;IAED,IAAI,gBAAgB,kBAiBnB;IAED,IAAI,UAAU,WA0Bb;;IAOK,iBAAiB;IAOvB,oBAAoB;IAMpB,wBAAwB,CACtB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE,MAAM;IAuBlB,MAAM;YA6BQ,OAAO;IAKrB,OAAO,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"PixivIcon.d.ts","sourceRoot":"","sources":["../src/PixivIcon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AASnD,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC;CAAG;AAExE,MAAM,WAAW,KACf,SAAQ,IAAI,CACV,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,EACvE,WAAW,GAAG,KAAK,CACpB;IACD,IAAI,EAAE,MAAM,aAAa,CAAA;IACzB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACnC,4BAA4B,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAI9C,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,KAAK,gBAAgB,GAAG,OAAO,CAAC,MAAM,aAAa,EAAE,aAAa,CAAC,CAAA;AACnE,KAAK,QAAQ,GAAG,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,GAC9C,KAAK,GACL,IAAI,CAAA;AAER,qBAAa,SAAU,SAAQ,WAAW;IACxC,MAAM,CAAC,QAAQ,CAAC,OAAO,gBAAe;IAEtC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,QAAQ,SAAS,IAAI,GACtB,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkB5B,MAAM,KAAK,kBAAkB,6DAE5B;IAED,OAAO,CAAC,UAAU,CAAC,CAAQ;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAsB;IACvC,OAAO,CAAC,SAAS,CAAQ;IAEzB,IAAI,KAAK;;;;MAqBR;IAED,IAAI,gBAAgB,kBAiBnB;IAED,IAAI,UAAU,WA0Bb;;IAOK,iBAAiB;IAOvB,oBAAoB;IAMpB,wBAAwB,CACtB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,QAAQ,EAAE,MAAM;IAuBlB,MAAM;YA6BQ,OAAO;IAKrB,OAAO,CAAC,gBAAgB;CAmBzB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import charcoalIconFiles from '@charcoal-ui/icon-files';
|
|
2
2
|
export default charcoalIconFiles;
|
|
3
3
|
export type KnownIconFile = keyof typeof charcoalIconFiles;
|
|
4
|
-
export declare const KNOWN_ICON_FILES: ("16/Add" | "16/Archive" | "16/ArrowDown" | "16/Artwork" | "16/Back" | "16/Book" | "16/BookmarkOff" | "16/BookmarkOn" | "16/Check" | "16/Comment" | "16/Dot" | "16/Error" | "16/Filter" | "16/ImageResponse" | "16/Info" | "16/Like" | "16/Menu" | "16/More" | "16/Nextworks" | "16/Pencil" | "16/Question" | "16/Ranking" | "16/Remove" | "16/Search" | "16/Smile" | "16/Speaker" | "16/View" | "16/Warning" | "24/Add" | "24/AddImage" | "24/AddModel" | "24/AddPeople" | "24/AddRubi" | "24/AddText" | "24/Alart" | "24/Announcement" | "24/Ar" | "24/Archive" | "24/ArrowDown" | "24/ArrowUp" | "24/Binet" | "24/Body" | "24/BodyEdit" | "24/Book" | "24/BringBackward" | "24/BringForward" | "24/Calendar" | "24/Camera" | "24/CameraVideo" | "24/ChangeCharactor" | "24/ChatBot" | "24/Check" | "24/ChromaticAberration" | "24/Click" | "24/Close" | "24/Codes" | "24/Collapse" | "24/CommentFill" | "24/CommentOutline" | "24/Contest" | "24/Contrast" | "24/Description" | "24/DeviceRotation" | "24/Discovery" | "24/Dot" | "24/DotAlt" | "24/Down" | "24/DownloadAlt" | "24/Duplicate" | "24/Dust" | "24/Emoji" | "24/Error" | "24/ErrorOctagon" | "24/Events" | "24/Expand" | "24/FaceEdit" | "24/Fashion" | "24/Feed" | "24/File" | "24/Filter" | "24/Flare" | "24/FormatAlignCenter" | "24/FormatAlignLeft" | "24/FormatAlignRight" | "24/FormatColorFill" | "24/FormatColorFillNoColor" | "24/FormatFontFamily" | "24/FormatFontSize" | "24/FormatLetterSpacing" | "24/FormatLineSpacing" | "24/Fov" | "24/FrameEffect" | "24/FrameSize" | "24/Gift" | "24/Glow" | "24/Groups" | "24/HairEdit" | "24/Hashtag" | "24/Hide" | "24/Home" | "24/Hue" | "24/Idea" | "24/Image" | "24/ImageAlt" | "24/ImageHidden" | "24/ImageReplace" | "24/Images" | "24/ImgContain" | "24/ImgCover" | "24/Index" | "24/Info" | "24/Invalid" | "24/Invoice" | "24/ItemRemove" | "24/LatestWorks" | "24/LikeOff" | "24/LikeOn" | "24/Link" | "24/List" | "24/LockLock" | "24/LockUnlock" | "24/Logout" | "24/Manga" | "24/Menu" | "24/Message" | "24/Microphone" | "24/MobilePhone" | "24/Move1" | "24/Next" | "24/NoImage" | "24/Notification" | "24/NotificationOff" | "24/Novels" | "24/OpenInNew" | "24/Options" | "24/OptionsAlt" | "24/Overlay" | "24/Palette" | "24/Pause" | "24/PauseAlt" | "24/Pencil" | "24/PencilAdd" | "24/PencilDraw" | "24/PencilLive" | "24/PencilText" | "24/Person" | "24/Play" | "24/Pose" | "24/Prev" | "24/Projects" | "24/PullDown" | "24/PullUp" | "24/Question" | "24/QuestionOutline" | "24/Ranking" | "24/ReadHorizontalLeft" | "24/ReadHorizontalRight" | "24/ReadVertical" | "24/Reload" | "24/ReloadLoop" | "24/Reorder" | "24/Roll" | "24/Rotate90DegreesC" | "24/Rotate90DegreesCc" | "24/RotateRight" | "24/Saturation" | "24/Save" | "24/Search" | "24/Send" | "24/Services" | "24/Set" | "24/Settings" | "24/ShareAndroid" | "24/ShareIos" | "24/Shopping" | "24/Show" | "24/ShowOutline" | "24/Shutter" | "24/Star" | "24/Subtract" | "24/Sun" | "24/Temperature" | "24/Text" | "24/Trash" | "24/TrashAlt" | "24/Up" | "24/Upload" | "24/UploadAlt" | "24/Usagi" | "24/UsagiAlt" | "24/Users" | "24/Video" | "24/ViewGrid2Columns" | "24/ViewGrid3Columns" | "24/ViewList" | "24/Warning" | "32/BookmarkOff" | "32/BookmarkOn" | "32/Camera" | "32/Close" | "32/Collapse" | "32/CommentOff" | "32/CommentOn" | "32/Delete" | "32/Dot" | "32/Edit" | "32/Expand" | "32/Gift" | "32/Home" | "32/HorizontalWriting" | "32/Index" | "32/LikeOff" | "32/LikeOn" | "32/LikeOnPrivate" | "32/Message" | "32/Next" | "32/Notification" | "32/NotificationOff" | "32/NovelViewerSettings" | "32/Pan" | "32/Prev" | "32/PullDown" | "32/PullUp" | "32/ReadHorizontalLeft" | "32/ReadHorizontalRight" | "32/ReadVertical" | "32/RollHorizontal" | "32/RollVertical" | "32/SansSerif" | "32/Serif" | "32/ShareAndroid" | "32/ShareIos" | "32/Shopping" | "32/Upload" | "32/User" | "32/VerticalWriting" | "32/ZoomIn" | "Inline/Add" | "Inline/BookmarkOff" | "Inline/BookmarkOn" | "Inline/Breadcrumbs" | "Inline/Check" | "Inline/Comment" | "Inline/ContextMenu" | "Inline/External" | "Inline/Filter" | "Inline/Folder" | "Inline/ImageResponse" | "Inline/Images" | "Inline/Like" | "Inline/LikeOff" | "Inline/List" | "Inline/Location" | "Inline/Lock" | "Inline/More" | "Inline/Nextworks" | "Inline/OpenInNew" | "Inline/Pencil" | "Inline/Remove" | "Inline/Smile" | "Inline/SmileOn" | "Inline/Users" | "Inline/View" | "Inline/ViewOutline")[];
|
|
4
|
+
export declare const KNOWN_ICON_FILES: ("16/Add" | "16/Archive" | "16/ArrowDown" | "16/Artwork" | "16/Back" | "16/Book" | "16/BookmarkOff" | "16/BookmarkOn" | "16/Check" | "16/Comment" | "16/Dot" | "16/Error" | "16/Filter" | "16/ImageResponse" | "16/Info" | "16/Like" | "16/Menu" | "16/More" | "16/Nextworks" | "16/Pencil" | "16/Question" | "16/Ranking" | "16/Remove" | "16/Search" | "16/Smile" | "16/Speaker" | "16/View" | "16/Warning" | "24/Add" | "24/AddImage" | "24/AddModel" | "24/AddPeople" | "24/AddRubi" | "24/AddText" | "24/Alart" | "24/Announcement" | "24/Ar" | "24/Archive" | "24/ArrowDown" | "24/ArrowUp" | "24/Binet" | "24/Body" | "24/BodyEdit" | "24/Book" | "24/BringBackward" | "24/BringForward" | "24/Calendar" | "24/Camera" | "24/CameraVideo" | "24/ChangeCharactor" | "24/ChatBot" | "24/Check" | "24/ChromaticAberration" | "24/Click" | "24/Close" | "24/Codes" | "24/Collapse" | "24/CommentFill" | "24/CommentOutline" | "24/Contest" | "24/Contrast" | "24/Description" | "24/DeviceRotation" | "24/Discovery" | "24/Dot" | "24/DotAlt" | "24/Down" | "24/DownloadAlt" | "24/Duplicate" | "24/Dust" | "24/Emoji" | "24/Error" | "24/ErrorOctagon" | "24/Events" | "24/Expand" | "24/FaceEdit" | "24/Fashion" | "24/Feed" | "24/File" | "24/Filter" | "24/Flare" | "24/FormatAlignCenter" | "24/FormatAlignJustified" | "24/FormatAlignLeft" | "24/FormatAlignRight" | "24/FormatColorFill" | "24/FormatColorFillNoColor" | "24/FormatFontFamily" | "24/FormatFontSize" | "24/FormatLetterSpacing" | "24/FormatLineSpacing" | "24/Fov" | "24/FrameEffect" | "24/FrameSize" | "24/Gift" | "24/Glow" | "24/Groups" | "24/HairEdit" | "24/Hashtag" | "24/Hide" | "24/Home" | "24/Hue" | "24/Idea" | "24/Image" | "24/ImageAlt" | "24/ImageHidden" | "24/ImageReplace" | "24/Images" | "24/ImgContain" | "24/ImgCover" | "24/Index" | "24/Info" | "24/Invalid" | "24/Invoice" | "24/ItemRemove" | "24/LatestWorks" | "24/LikeOff" | "24/LikeOn" | "24/Link" | "24/List" | "24/LockLock" | "24/LockUnlock" | "24/Logout" | "24/Manga" | "24/Menu" | "24/Message" | "24/Microphone" | "24/MobilePhone" | "24/Move1" | "24/Next" | "24/NoImage" | "24/Notification" | "24/NotificationOff" | "24/Novels" | "24/OpenInNew" | "24/Options" | "24/OptionsAlt" | "24/Overlay" | "24/Palette" | "24/Pause" | "24/PauseAlt" | "24/Pencil" | "24/PencilAdd" | "24/PencilDraw" | "24/PencilLive" | "24/PencilText" | "24/Person" | "24/Play" | "24/Pose" | "24/Prev" | "24/Projects" | "24/PullDown" | "24/PullUp" | "24/Question" | "24/QuestionOutline" | "24/Ranking" | "24/ReadHorizontalLeft" | "24/ReadHorizontalRight" | "24/ReadVertical" | "24/Redo" | "24/Reload" | "24/ReloadLoop" | "24/Reorder" | "24/Roll" | "24/Rotate90DegreesC" | "24/Rotate90DegreesCc" | "24/RotateRight" | "24/Saturation" | "24/Save" | "24/Search" | "24/Send" | "24/Services" | "24/Set" | "24/Settings" | "24/ShareAndroid" | "24/ShareIos" | "24/Shopping" | "24/Show" | "24/ShowOutline" | "24/Shutter" | "24/Star" | "24/Subtract" | "24/Sun" | "24/Temperature" | "24/Text" | "24/Trash" | "24/TrashAlt" | "24/Undo" | "24/Up" | "24/Upload" | "24/UploadAlt" | "24/Usagi" | "24/UsagiAlt" | "24/Users" | "24/Video" | "24/ViewGrid2Columns" | "24/ViewGrid3Columns" | "24/ViewList" | "24/Warning" | "32/BookmarkOff" | "32/BookmarkOn" | "32/Camera" | "32/Close" | "32/Collapse" | "32/CommentOff" | "32/CommentOn" | "32/Delete" | "32/Dot" | "32/Edit" | "32/Expand" | "32/Gift" | "32/Home" | "32/HorizontalWriting" | "32/Index" | "32/LikeOff" | "32/LikeOn" | "32/LikeOnPrivate" | "32/Message" | "32/Next" | "32/Notification" | "32/NotificationOff" | "32/NovelViewerSettings" | "32/Pan" | "32/Prev" | "32/PullDown" | "32/PullUp" | "32/ReadHorizontalLeft" | "32/ReadHorizontalRight" | "32/ReadVertical" | "32/RollHorizontal" | "32/RollVertical" | "32/SansSerif" | "32/Serif" | "32/ShareAndroid" | "32/ShareIos" | "32/Shopping" | "32/Upload" | "32/User" | "32/VerticalWriting" | "32/ZoomIn" | "Inline/Add" | "Inline/BookmarkOff" | "Inline/BookmarkOn" | "Inline/Breadcrumbs" | "Inline/Check" | "Inline/Comment" | "Inline/ContextMenu" | "Inline/External" | "Inline/Filter" | "Inline/Folder" | "Inline/ImageResponse" | "Inline/Images" | "Inline/Like" | "Inline/LikeOff" | "Inline/List" | "Inline/Location" | "Inline/Lock" | "Inline/More" | "Inline/Nextworks" | "Inline/OpenInNew" | "Inline/Pencil" | "Inline/Remove" | "Inline/Smile" | "Inline/SmileOn" | "Inline/Users" | "Inline/View" | "Inline/ViewOutline")[];
|
|
5
5
|
export declare function isKnownIconFile(name: string): name is KnownIconFile;
|
|
6
6
|
//# sourceMappingURL=charcoalIconFiles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"charcoalIconFiles.d.ts","sourceRoot":"","sources":["../src/charcoalIconFiles.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,yBAAyB,CAAA;AAEvD,eAAe,iBAAiB,CAAA;AAChC,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,iBAAiB,CAAA;AAC1D,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"charcoalIconFiles.d.ts","sourceRoot":"","sources":["../src/charcoalIconFiles.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,yBAAyB,CAAA;AAEvD,eAAe,iBAAiB,CAAA;AAChC,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,iBAAiB,CAAA;AAC1D,eAAO,MAAM,gBAAgB,+wIAET,CAAA;AAEpB,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,aAAa,CAEnE"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -313,8 +313,9 @@ var PixivIcon = class extends HTMLElement {
|
|
|
313
313
|
waitUntilVisible() {
|
|
314
314
|
return new Promise((resolve) => {
|
|
315
315
|
this.observer = new IntersectionObserver(
|
|
316
|
-
(
|
|
317
|
-
|
|
316
|
+
(entries) => {
|
|
317
|
+
const isIntersecting = entries.some((entry) => entry.isIntersecting);
|
|
318
|
+
if (isIntersecting) {
|
|
318
319
|
this.observer?.disconnect();
|
|
319
320
|
this.observer = void 0;
|
|
320
321
|
resolve();
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/PixivIcon.ts","../src/charcoalIconFiles.ts","../src/loaders/PixivIconLoadError.ts","../src/loaders/CharcoalIconFilesLoader.ts","../src/loaders/CustomIconLoader.ts","../src/loaders/index.ts","../src/ssr.ts"],"sourcesContent":["import { PixivIcon, Props } from './PixivIcon'\nimport { __SERVER__ } from './ssr'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { KNOWN_ICON_FILES } from './charcoalIconFiles'\nexport { PixivIconLoadError } from './loaders/PixivIconLoadError'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\nif (!__SERVER__) {\n // TODO: HMR対応\n if (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n }\n}\n","import type React from 'react'\nimport warning from 'warning'\nimport { KnownIconFile } from './charcoalIconFiles'\nimport { getIcon, addCustomIcon } from './loaders'\nimport { __SERVER__ } from './ssr'\nimport DOMPurify from 'dompurify'\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className' | 'css'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends HTMLElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')\n if (__SERVER__) {\n return\n }\n\n Object.entries(map).forEach(([name, filePathOrUrl]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n addCustomIcon(name, filePathOrUrl)\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n private isVisible = false\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<(typeof attributes)[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n async connectedCallback() {\n this.render()\n await this.waitUntilVisible()\n this.isVisible = true\n await this.loadSvg(this.props.name)\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n this.isVisible = false\n }\n\n attributeChangedCallback(\n attr: string,\n _oldValue: string | null,\n newValue: string\n ) {\n // 非表示の場合はロードしない\n if (!this.isVisible) {\n return\n }\n\n // name が変更された場合必ず再読み込みを試みる\n if (attr === 'name') {\n void this.loadSvg(newValue)\n return\n }\n\n // SVG が読み込み済み && scale などの変更だけならそこだけ反映すればいい\n if (this.svgContent !== undefined) {\n this.render()\n return\n }\n\n // まだ SVG が読み込めてないなら load\n void this.loadSvg(this.props.name)\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n const style = DOMPurify.sanitize(\n `<style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,\n { ALLOWED_TAGS: ['style'], FORCE_BODY: true }\n )\n\n const svg = DOMPurify.sanitize(\n this.svgContent !== undefined\n ? this.svgContent\n : `<svg viewBox=\"0 0 ${size} ${size}\"></svg>`,\n { USE_PROFILES: { svg: true, svgFilters: true } }\n )\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.shadowRoot!.innerHTML = style + svg\n }\n\n private async loadSvg(name: string) {\n this.svgContent = await getIcon(name)\n this.render()\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import charcoalIconFiles from '@charcoal-ui/icon-files'\n\nexport default charcoalIconFiles\nexport type KnownIconFile = keyof typeof charcoalIconFiles\nexport const KNOWN_ICON_FILES = Object.keys(\n charcoalIconFiles\n) as KnownIconFile[]\n\nexport function isKnownIconFile(name: string): name is KnownIconFile {\n return name in charcoalIconFiles\n}\n","export class PixivIconLoadError extends Error {\n constructor(name: string, cause: unknown) {\n const message = formatMessage(name, cause)\n\n super(message, { cause })\n this.name = 'PixivIconLoadError'\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\nfunction formatMessage(name: string, cause: unknown) {\n const message = `Failed to fetch <pixiv-icon name=\"${name}\">`\n if (cause == null) {\n return message\n }\n\n if (cause instanceof Error) {\n return `${message}: ${cause.toString()})`\n }\n\n return `${message}: ${JSON.stringify(cause)})`\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\nimport charcoalIconFiles, { KnownIconFile } from '../charcoalIconFiles'\n\n/**\n * `@charcoal-ui/icon-files` に収録されているアイコンを取ってくる\n */\nexport class CharcoalIconFilesLoader implements Loadable {\n private _name: KnownIconFile\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: KnownIconFile) {\n this._name = name\n }\n\n get importIconFile() {\n return charcoalIconFiles[this._name]\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = this.importIconFile()\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\n\n/**\n * `PixivIcon.extend()` で登録されたカスタムのアイコンを取得する\n */\nexport class CustomIconLoader implements Loadable {\n private _name: string\n private _filePathOrUrl: string\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: string, filePathOrUrl: string) {\n this._name = name\n this._filePathOrUrl = filePathOrUrl\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = fetch(this._filePathOrUrl)\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(this._name, 'Response is not ok')\n }\n\n return response.text()\n })\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { isKnownIconFile } from '../charcoalIconFiles'\nimport { CharcoalIconFilesLoader } from './CharcoalIconFilesLoader'\nimport { CustomIconLoader } from './CustomIconLoader'\nimport { Loadable } from './Loadable'\nimport { PixivIconLoadError } from './PixivIconLoadError'\n\n/**\n * icon をロードするオブジェクトのプール。Loader のインスタンスは作り次第ここに入れる\n *\n * 同じアイコンへの複数回のリクエストが起きないためには、Loader がこの中でユニークでないと行けない\n */\nconst loaders = new Map<string, Loadable>()\n\nexport function addCustomIcon(name: string, filePathOrUrl: string) {\n loaders.set(name, new CustomIconLoader(name, filePathOrUrl))\n}\n\nexport async function getIcon(name: string) {\n const loader = resolveIconLoader(name)\n if (loader == null) {\n throw new PixivIconLoadError(name, 'Loader was not found')\n }\n\n return loader.fetch().catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n\n throw new PixivIconLoadError(name, e)\n })\n}\n\nfunction resolveIconLoader(name: string) {\n // 登録済み or キャッシュ済みの場合\n // addCustomIcon で登録された CustomIconLoader は常にこっちを通る\n const registeredLoader = loaders.get(name)\n if (registeredLoader) {\n return registeredLoader\n }\n\n // `@charcoal-ui/icon-files` に収録されているアイコンにはこれを返す\n if (isKnownIconFile(name)) {\n const charcoalIconFilesLoader = new CharcoalIconFilesLoader(name)\n\n loaders.set(name, charcoalIconFilesLoader)\n return charcoalIconFilesLoader\n }\n\n // 存在しないアイコンにはこれを返す\n return null\n}\n","export const __SERVER__ = typeof window === 'undefined'\n\nconst CAN_USE_DOM = typeof HTMLElement !== 'undefined'\n\n// Workaround: `extends HTMLElement` の形式でないとbabelのトランスパイルがおかしくなる\nif (__SERVER__ || !CAN_USE_DOM) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any\n globalThis.HTMLElement = class {} as any\n}\n"],"mappings":"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","names":["charcoalIconFiles","warning","DOMPurify"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/PixivIcon.ts","../src/charcoalIconFiles.ts","../src/loaders/PixivIconLoadError.ts","../src/loaders/CharcoalIconFilesLoader.ts","../src/loaders/CustomIconLoader.ts","../src/loaders/index.ts","../src/ssr.ts"],"sourcesContent":["import { PixivIcon, Props } from './PixivIcon'\nimport { __SERVER__ } from './ssr'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { KNOWN_ICON_FILES } from './charcoalIconFiles'\nexport { PixivIconLoadError } from './loaders/PixivIconLoadError'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\nif (!__SERVER__) {\n // TODO: HMR対応\n if (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n }\n}\n","import type React from 'react'\nimport warning from 'warning'\nimport { KnownIconFile } from './charcoalIconFiles'\nimport { getIcon, addCustomIcon } from './loaders'\nimport { __SERVER__ } from './ssr'\nimport DOMPurify from 'dompurify'\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className' | 'css'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends HTMLElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')\n if (__SERVER__) {\n return\n }\n\n Object.entries(map).forEach(([name, filePathOrUrl]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n addCustomIcon(name, filePathOrUrl)\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n private isVisible = false\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<(typeof attributes)[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n async connectedCallback() {\n this.render()\n await this.waitUntilVisible()\n this.isVisible = true\n await this.loadSvg(this.props.name)\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n this.isVisible = false\n }\n\n attributeChangedCallback(\n attr: string,\n _oldValue: string | null,\n newValue: string\n ) {\n // 非表示の場合はロードしない\n if (!this.isVisible) {\n return\n }\n\n // name が変更された場合必ず再読み込みを試みる\n if (attr === 'name') {\n void this.loadSvg(newValue)\n return\n }\n\n // SVG が読み込み済み && scale などの変更だけならそこだけ反映すればいい\n if (this.svgContent !== undefined) {\n this.render()\n return\n }\n\n // まだ SVG が読み込めてないなら load\n void this.loadSvg(this.props.name)\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n const style = DOMPurify.sanitize(\n `<style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,\n { ALLOWED_TAGS: ['style'], FORCE_BODY: true }\n )\n\n const svg = DOMPurify.sanitize(\n this.svgContent !== undefined\n ? this.svgContent\n : `<svg viewBox=\"0 0 ${size} ${size}\"></svg>`,\n { USE_PROFILES: { svg: true, svgFilters: true } }\n )\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.shadowRoot!.innerHTML = style + svg\n }\n\n private async loadSvg(name: string) {\n this.svgContent = await getIcon(name)\n this.render()\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n (entries) => {\n // In Chromium based browsers, multiple entries can be returned even only observe once.\n // Here, we don't care about the entry time but only if isIntersecting happened.\n const isIntersecting = entries.some((entry) => entry.isIntersecting)\n if (isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import charcoalIconFiles from '@charcoal-ui/icon-files'\n\nexport default charcoalIconFiles\nexport type KnownIconFile = keyof typeof charcoalIconFiles\nexport const KNOWN_ICON_FILES = Object.keys(\n charcoalIconFiles\n) as KnownIconFile[]\n\nexport function isKnownIconFile(name: string): name is KnownIconFile {\n return name in charcoalIconFiles\n}\n","export class PixivIconLoadError extends Error {\n constructor(name: string, cause: unknown) {\n const message = formatMessage(name, cause)\n\n super(message, { cause })\n this.name = 'PixivIconLoadError'\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\nfunction formatMessage(name: string, cause: unknown) {\n const message = `Failed to fetch <pixiv-icon name=\"${name}\">`\n if (cause == null) {\n return message\n }\n\n if (cause instanceof Error) {\n return `${message}: ${cause.toString()})`\n }\n\n return `${message}: ${JSON.stringify(cause)})`\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\nimport charcoalIconFiles, { KnownIconFile } from '../charcoalIconFiles'\n\n/**\n * `@charcoal-ui/icon-files` に収録されているアイコンを取ってくる\n */\nexport class CharcoalIconFilesLoader implements Loadable {\n private _name: KnownIconFile\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: KnownIconFile) {\n this._name = name\n }\n\n get importIconFile() {\n return charcoalIconFiles[this._name]\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = this.importIconFile()\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\n\n/**\n * `PixivIcon.extend()` で登録されたカスタムのアイコンを取得する\n */\nexport class CustomIconLoader implements Loadable {\n private _name: string\n private _filePathOrUrl: string\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: string, filePathOrUrl: string) {\n this._name = name\n this._filePathOrUrl = filePathOrUrl\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = fetch(this._filePathOrUrl)\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(this._name, 'Response is not ok')\n }\n\n return response.text()\n })\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { isKnownIconFile } from '../charcoalIconFiles'\nimport { CharcoalIconFilesLoader } from './CharcoalIconFilesLoader'\nimport { CustomIconLoader } from './CustomIconLoader'\nimport { Loadable } from './Loadable'\nimport { PixivIconLoadError } from './PixivIconLoadError'\n\n/**\n * icon をロードするオブジェクトのプール。Loader のインスタンスは作り次第ここに入れる\n *\n * 同じアイコンへの複数回のリクエストが起きないためには、Loader がこの中でユニークでないと行けない\n */\nconst loaders = new Map<string, Loadable>()\n\nexport function addCustomIcon(name: string, filePathOrUrl: string) {\n loaders.set(name, new CustomIconLoader(name, filePathOrUrl))\n}\n\nexport async function getIcon(name: string) {\n const loader = resolveIconLoader(name)\n if (loader == null) {\n throw new PixivIconLoadError(name, 'Loader was not found')\n }\n\n return loader.fetch().catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n\n throw new PixivIconLoadError(name, e)\n })\n}\n\nfunction resolveIconLoader(name: string) {\n // 登録済み or キャッシュ済みの場合\n // addCustomIcon で登録された CustomIconLoader は常にこっちを通る\n const registeredLoader = loaders.get(name)\n if (registeredLoader) {\n return registeredLoader\n }\n\n // `@charcoal-ui/icon-files` に収録されているアイコンにはこれを返す\n if (isKnownIconFile(name)) {\n const charcoalIconFilesLoader = new CharcoalIconFilesLoader(name)\n\n loaders.set(name, charcoalIconFilesLoader)\n return charcoalIconFilesLoader\n }\n\n // 存在しないアイコンにはこれを返す\n return null\n}\n","export const __SERVER__ = typeof window === 'undefined'\n\nconst CAN_USE_DOM = typeof HTMLElement !== 'undefined'\n\n// Workaround: `extends HTMLElement` の形式でないとbabelのトランスパイルがおかしくなる\nif (__SERVER__ || !CAN_USE_DOM) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any\n globalThis.HTMLElement = class {} as any\n}\n"],"mappings":"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","names":["charcoalIconFiles","warning","DOMPurify"]}
|
package/dist/index.esm.js
CHANGED
|
@@ -281,8 +281,9 @@ var PixivIcon = class extends HTMLElement {
|
|
|
281
281
|
waitUntilVisible() {
|
|
282
282
|
return new Promise((resolve) => {
|
|
283
283
|
this.observer = new IntersectionObserver(
|
|
284
|
-
(
|
|
285
|
-
|
|
284
|
+
(entries) => {
|
|
285
|
+
const isIntersecting = entries.some((entry) => entry.isIntersecting);
|
|
286
|
+
if (isIntersecting) {
|
|
286
287
|
this.observer?.disconnect();
|
|
287
288
|
this.observer = void 0;
|
|
288
289
|
resolve();
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PixivIcon.ts","../src/charcoalIconFiles.ts","../src/loaders/PixivIconLoadError.ts","../src/loaders/CharcoalIconFilesLoader.ts","../src/loaders/CustomIconLoader.ts","../src/loaders/index.ts","../src/ssr.ts","../src/index.ts"],"sourcesContent":["import type React from 'react'\nimport warning from 'warning'\nimport { KnownIconFile } from './charcoalIconFiles'\nimport { getIcon, addCustomIcon } from './loaders'\nimport { __SERVER__ } from './ssr'\nimport DOMPurify from 'dompurify'\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className' | 'css'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends HTMLElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')\n if (__SERVER__) {\n return\n }\n\n Object.entries(map).forEach(([name, filePathOrUrl]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n addCustomIcon(name, filePathOrUrl)\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n private isVisible = false\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<(typeof attributes)[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n async connectedCallback() {\n this.render()\n await this.waitUntilVisible()\n this.isVisible = true\n await this.loadSvg(this.props.name)\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n this.isVisible = false\n }\n\n attributeChangedCallback(\n attr: string,\n _oldValue: string | null,\n newValue: string\n ) {\n // 非表示の場合はロードしない\n if (!this.isVisible) {\n return\n }\n\n // name が変更された場合必ず再読み込みを試みる\n if (attr === 'name') {\n void this.loadSvg(newValue)\n return\n }\n\n // SVG が読み込み済み && scale などの変更だけならそこだけ反映すればいい\n if (this.svgContent !== undefined) {\n this.render()\n return\n }\n\n // まだ SVG が読み込めてないなら load\n void this.loadSvg(this.props.name)\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n const style = DOMPurify.sanitize(\n `<style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,\n { ALLOWED_TAGS: ['style'], FORCE_BODY: true }\n )\n\n const svg = DOMPurify.sanitize(\n this.svgContent !== undefined\n ? this.svgContent\n : `<svg viewBox=\"0 0 ${size} ${size}\"></svg>`,\n { USE_PROFILES: { svg: true, svgFilters: true } }\n )\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.shadowRoot!.innerHTML = style + svg\n }\n\n private async loadSvg(name: string) {\n this.svgContent = await getIcon(name)\n this.render()\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n ([first]) => {\n if (first.isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import charcoalIconFiles from '@charcoal-ui/icon-files'\n\nexport default charcoalIconFiles\nexport type KnownIconFile = keyof typeof charcoalIconFiles\nexport const KNOWN_ICON_FILES = Object.keys(\n charcoalIconFiles\n) as KnownIconFile[]\n\nexport function isKnownIconFile(name: string): name is KnownIconFile {\n return name in charcoalIconFiles\n}\n","export class PixivIconLoadError extends Error {\n constructor(name: string, cause: unknown) {\n const message = formatMessage(name, cause)\n\n super(message, { cause })\n this.name = 'PixivIconLoadError'\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\nfunction formatMessage(name: string, cause: unknown) {\n const message = `Failed to fetch <pixiv-icon name=\"${name}\">`\n if (cause == null) {\n return message\n }\n\n if (cause instanceof Error) {\n return `${message}: ${cause.toString()})`\n }\n\n return `${message}: ${JSON.stringify(cause)})`\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\nimport charcoalIconFiles, { KnownIconFile } from '../charcoalIconFiles'\n\n/**\n * `@charcoal-ui/icon-files` に収録されているアイコンを取ってくる\n */\nexport class CharcoalIconFilesLoader implements Loadable {\n private _name: KnownIconFile\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: KnownIconFile) {\n this._name = name\n }\n\n get importIconFile() {\n return charcoalIconFiles[this._name]\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = this.importIconFile()\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\n\n/**\n * `PixivIcon.extend()` で登録されたカスタムのアイコンを取得する\n */\nexport class CustomIconLoader implements Loadable {\n private _name: string\n private _filePathOrUrl: string\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: string, filePathOrUrl: string) {\n this._name = name\n this._filePathOrUrl = filePathOrUrl\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = fetch(this._filePathOrUrl)\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(this._name, 'Response is not ok')\n }\n\n return response.text()\n })\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { isKnownIconFile } from '../charcoalIconFiles'\nimport { CharcoalIconFilesLoader } from './CharcoalIconFilesLoader'\nimport { CustomIconLoader } from './CustomIconLoader'\nimport { Loadable } from './Loadable'\nimport { PixivIconLoadError } from './PixivIconLoadError'\n\n/**\n * icon をロードするオブジェクトのプール。Loader のインスタンスは作り次第ここに入れる\n *\n * 同じアイコンへの複数回のリクエストが起きないためには、Loader がこの中でユニークでないと行けない\n */\nconst loaders = new Map<string, Loadable>()\n\nexport function addCustomIcon(name: string, filePathOrUrl: string) {\n loaders.set(name, new CustomIconLoader(name, filePathOrUrl))\n}\n\nexport async function getIcon(name: string) {\n const loader = resolveIconLoader(name)\n if (loader == null) {\n throw new PixivIconLoadError(name, 'Loader was not found')\n }\n\n return loader.fetch().catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n\n throw new PixivIconLoadError(name, e)\n })\n}\n\nfunction resolveIconLoader(name: string) {\n // 登録済み or キャッシュ済みの場合\n // addCustomIcon で登録された CustomIconLoader は常にこっちを通る\n const registeredLoader = loaders.get(name)\n if (registeredLoader) {\n return registeredLoader\n }\n\n // `@charcoal-ui/icon-files` に収録されているアイコンにはこれを返す\n if (isKnownIconFile(name)) {\n const charcoalIconFilesLoader = new CharcoalIconFilesLoader(name)\n\n loaders.set(name, charcoalIconFilesLoader)\n return charcoalIconFilesLoader\n }\n\n // 存在しないアイコンにはこれを返す\n return null\n}\n","export const __SERVER__ = typeof window === 'undefined'\n\nconst CAN_USE_DOM = typeof HTMLElement !== 'undefined'\n\n// Workaround: `extends HTMLElement` の形式でないとbabelのトランスパイルがおかしくなる\nif (__SERVER__ || !CAN_USE_DOM) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any\n globalThis.HTMLElement = class {} as any\n}\n","import { PixivIcon, Props } from './PixivIcon'\nimport { __SERVER__ } from './ssr'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { KNOWN_ICON_FILES } from './charcoalIconFiles'\nexport { PixivIconLoadError } from './loaders/PixivIconLoadError'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\nif (!__SERVER__) {\n // TODO: HMR対応\n if (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n }\n}\n"],"mappings":";;;;;;;;AACA,OAAO,aAAa;;;ACDpB,OAAO,uBAAuB;AAE9B,IAAO,4BAAQ;AAER,IAAM,mBAAmB,OAAO;AAAA,EACrC;AACF;AAEO,SAAS,gBAAgB,MAAqC;AACnE,SAAO,QAAQ;AACjB;;;ACVO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,MAAc,OAAgB;AACxC,UAAM,UAAU,cAAc,MAAM,KAAK;AAEzC,UAAM,SAAS,EAAE,MAAM,CAAC;AACxB,SAAK,OAAO;AACZ,WAAO,eAAe,MAAM,WAAW,SAAS;AAAA,EAClD;AACF;AAEA,SAAS,cAAc,MAAc,OAAgB;AACnD,QAAM,UAAU,qCAAqC;AACrD,MAAI,SAAS,MAAM;AACjB,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,OAAO;AAC1B,WAAO,GAAG,YAAY,MAAM,SAAS;AAAA,EACvC;AAEA,SAAO,GAAG,YAAY,KAAK,UAAU,KAAK;AAC5C;;;ACdO,IAAM,0BAAN,MAAkD;AAAA,EAC/C;AAAA,EACA,aAAiC;AAAA,EACjC,WAAwC;AAAA,EAEhD,YAAY,MAAqB;AAC/B,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,IAAI,iBAAiB;AACnB,WAAO,0BAAkB,KAAK;AAAA,EAChC;AAAA,EAEA,MAAM,QAAyB;AAC7B,QAAI,KAAK,eAAe,QAAW;AACjC,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,KAAK,UAAU;AACjB,aAAO,KAAK;AAAA,IACd;AAEA,SAAK,WAAW,KAAK,eAAe,EACjC,KAAK,CAAC,QAAQ;AACb,WAAK,aAAa;AAClB,aAAO,KAAK;AAAA,IACd,CAAC,EACA,MAAM,CAAC,MAAM;AACZ,YAAM,IAAI,mBAAmB,KAAK,OAAO,CAAC;AAAA,IAC5C,CAAC,EACA,QAAQ,MAAM;AACb,WAAK,WAAW;AAAA,IAClB,CAAC;AAEH,WAAO,KAAK;AAAA,EACd;AACF;;;ACrCO,IAAM,mBAAN,MAA2C;AAAA,EACxC;AAAA,EACA;AAAA,EACA,aAAiC;AAAA,EACjC,WAAwC;AAAA,EAEhD,YAAY,MAAc,eAAuB;AAC/C,SAAK,QAAQ;AACb,SAAK,iBAAiB;AAAA,EACxB;AAAA,EAEA,MAAM,QAAyB;AAC7B,QAAI,KAAK,eAAe,QAAW;AACjC,aAAO,KAAK;AAAA,IACd;AAEA,QAAI,KAAK,UAAU;AACjB,aAAO,KAAK;AAAA,IACd;AAEA,SAAK,WAAW,MAAM,KAAK,cAAc,EACtC,KAAK,CAAC,aAAa;AAClB,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,mBAAmB,KAAK,OAAO,oBAAoB;AAAA,MAC/D;AAEA,aAAO,SAAS,KAAK;AAAA,IACvB,CAAC,EACA,KAAK,CAAC,QAAQ;AACb,WAAK,aAAa;AAClB,aAAO,KAAK;AAAA,IACd,CAAC,EACA,MAAM,CAAC,MAAM;AACZ,UAAI,aAAa,oBAAoB;AACnC,cAAM;AAAA,MACR;AACA,YAAM,IAAI,mBAAmB,KAAK,OAAO,CAAC;AAAA,IAC5C,CAAC,EACA,QAAQ,MAAM;AACb,WAAK,WAAW;AAAA,IAClB,CAAC;AAEH,WAAO,KAAK;AAAA,EACd;AACF;;;ACvCA,IAAM,UAAU,oBAAI,IAAsB;AAEnC,SAAS,cAAc,MAAc,eAAuB;AACjE,UAAQ,IAAI,MAAM,IAAI,iBAAiB,MAAM,aAAa,CAAC;AAC7D;AAEA,eAAsB,QAAQ,MAAc;AAC1C,QAAM,SAAS,kBAAkB,IAAI;AACrC,MAAI,UAAU,MAAM;AAClB,UAAM,IAAI,mBAAmB,MAAM,sBAAsB;AAAA,EAC3D;AAEA,SAAO,OAAO,MAAM,EAAE,MAAM,CAAC,MAAM;AACjC,QAAI,aAAa,oBAAoB;AACnC,YAAM;AAAA,IACR;AAEA,UAAM,IAAI,mBAAmB,MAAM,CAAC;AAAA,EACtC,CAAC;AACH;AAEA,SAAS,kBAAkB,MAAc;AAGvC,QAAM,mBAAmB,QAAQ,IAAI,IAAI;AACzC,MAAI,kBAAkB;AACpB,WAAO;AAAA,EACT;AAGA,MAAI,gBAAgB,IAAI,GAAG;AACzB,UAAM,0BAA0B,IAAI,wBAAwB,IAAI;AAEhE,YAAQ,IAAI,MAAM,uBAAuB;AACzC,WAAO;AAAA,EACT;AAGA,SAAO;AACT;;;AClDO,IAAM,aAAa,OAAO,WAAW;AAE5C,IAAM,cAAc,OAAO,gBAAgB;AAG3C,IAAI,cAAc,CAAC,aAAa;AAE9B,aAAW,cAAc,MAAM;AAAA,EAAC;AAClC;;;ANHA,OAAO,eAAe;AAEtB,IAAM,aAAa,CAAC,QAAQ,SAAS,4BAA4B;AAEjE,IAAM,cAAc;AAuBb,IAAM,YAAN,cAAwB,YAAY;AAAA,EAGzC,OAAO,OACL,KAGA;AACA,YAAQ,CAAC,YAAY,oDAAoD;AACzE,QAAI,YAAY;AACd;AAAA,IACF;AAEA,WAAO,QAAQ,GAAG,EAAE,QAAQ,CAAC,CAAC,MAAM,aAAa,MAAM;AACrD,UAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,cAAM,IAAI;AAAA,UACR,GAAG;AAAA,QACL;AAAA,MACF;AAEA,oBAAc,MAAM,aAAa;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEA,WAAW,qBAAqB;AAC9B,WAAO;AAAA,EACT;AAAA,EAEQ;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EAEpB,IAAI,QAAQ;AACV,UAAM,UAAU,OAAO;AAAA,MACrB,WAAW,IAAI,CAAC,cAAc,CAAC,WAAW,KAAK,aAAa,SAAS,CAAC,CAAC;AAAA,IACzE;AAEA,UAAM,OAAO,QAAQ;AAErB,QAAI,SAAS,MAAM;AACjB,YAAM,IAAI,UAAU,8BAA8B;AAAA,IACpD;AAEA,QAAI,CAAC,KAAK,SAAS,GAAG,GAAG;AACvB,YAAM,IAAI;AAAA,QACR,GAAG;AAAA,MACL;AAAA,IACF;AAEA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,mBAAmB;AACrB,QAAI,KAAK,MAAM,kCAAkC,MAAM;AACrD,aAAO;AAAA,IACT;AAEA,UAAM,CAAC,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,GAAG;AACxC,UAAM,QAAQ,OAAO,KAAK,MAAM,6BAA6B;AAE7D,YAAQ,MAAM;AAAA,MACZ,KAAK,UAAU;AACb,eAAO,KAAK;AAAA,MACd;AAAA,MAEA,SAAS;AACP,eAAO,OAAO,IAAI,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,aAAa;AACf,UAAM,CAAC,IAAI,IAAI,KAAK,MAAM,KAAK,MAAM,GAAG;AAExC,UAAM,QAAQ,OAAO,KAAK,MAAM,SAAS,GAAG;AAE5C,YAAQ,MAAM;AAAA,MACZ,KAAK,UAAU;AACb,gBAAQ,OAAO;AAAA,UACb,KAAK,GAAG;AACN,mBAAO;AAAA,UACT;AAAA,UAEA,SAAS;AACP,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,MAEA,KAAK,MAAM;AACT,eAAO,OAAO,IAAI,IAAI;AAAA,MACxB;AAAA,MAEA,SAAS;AACP,eAAO,OAAO,IAAI;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc;AACZ,UAAM;AACN,SAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,oBAAoB;AACxB,SAAK,OAAO;AACZ,UAAM,KAAK,iBAAiB;AAC5B,SAAK,YAAY;AACjB,UAAM,KAAK,QAAQ,KAAK,MAAM,IAAI;AAAA,EACpC;AAAA,EAEA,uBAAuB;AACrB,SAAK,UAAU,WAAW;AAC1B,SAAK,WAAW;AAChB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,yBACE,MACA,WACA,UACA;AAEA,QAAI,CAAC,KAAK,WAAW;AACnB;AAAA,IACF;AAGA,QAAI,SAAS,QAAQ;AACnB,WAAK,KAAK,QAAQ,QAAQ;AAC1B;AAAA,IACF;AAGA,QAAI,KAAK,eAAe,QAAW;AACjC,WAAK,OAAO;AACZ;AAAA,IACF;AAGA,SAAK,KAAK,QAAQ,KAAK,MAAM,IAAI;AAAA,EACnC;AAAA,EAEA,SAAS;AACP,UAAM,OAAO,KAAK,oBAAoB,KAAK;AAE3C,UAAM,QAAQ,UAAU;AAAA,MACtB;AAAA;AAAA;AAAA,cAGQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQR,EAAE,cAAc,CAAC,OAAO,GAAG,YAAY,KAAK;AAAA,IAC9C;AAEA,UAAM,MAAM,UAAU;AAAA,MACpB,KAAK,eAAe,SAChB,KAAK,aACL,qBAAqB,QAAQ;AAAA,MACjC,EAAE,cAAc,EAAE,KAAK,MAAM,YAAY,KAAK,EAAE;AAAA,IAClD;AAGA,SAAK,WAAY,YAAY,QAAQ;AAAA,EACvC;AAAA,EAEA,MAAc,QAAQ,MAAc;AAClC,SAAK,aAAa,MAAM,QAAQ,IAAI;AACpC,SAAK,OAAO;AAAA,EACd;AAAA,EAEQ,mBAAmB;AACzB,WAAO,IAAI,QAAc,CAAC,YAAY;AACpC,WAAK,WAAW,IAAI;AAAA,QAClB,CAAC,CAAC,KAAK,MAAM;AACX,cAAI,MAAM,gBAAgB;AACxB,iBAAK,UAAU,WAAW;AAC1B,iBAAK,WAAW;AAChB,oBAAQ;AAAA,UACV;AAAA,QACF;AAAA,QACA,EAAE,YAAY,GAAG,gBAAgB;AAAA,MACnC;AAEA,WAAK,SAAS,QAAQ,IAAI;AAAA,IAC5B,CAAC;AAAA,EACH;AACF;AAnME,cADW,WACK,WAAU;;;AOd5B,IAAI,CAAC,YAAY;AAEf,MAAI,CAAC,OAAO,eAAe,IAAI,UAAU,OAAO,GAAG;AACjD,WAAO,YAAY;AACnB,WAAO,eAAe,OAAO,UAAU,SAAS,SAAS;AAAA,EAC3D;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/PixivIcon.ts","../src/charcoalIconFiles.ts","../src/loaders/PixivIconLoadError.ts","../src/loaders/CharcoalIconFilesLoader.ts","../src/loaders/CustomIconLoader.ts","../src/loaders/index.ts","../src/ssr.ts","../src/index.ts"],"sourcesContent":["import type React from 'react'\nimport warning from 'warning'\nimport { KnownIconFile } from './charcoalIconFiles'\nimport { getIcon, addCustomIcon } from './loaders'\nimport { __SERVER__ } from './ssr'\nimport DOMPurify from 'dompurify'\n\nconst attributes = ['name', 'scale', 'unsafe-non-guideline-scale'] as const\n\nconst ROOT_MARGIN = 50\n\nexport interface KnownIconType extends Record<KnownIconFile, unknown> {}\n\nexport interface Props\n extends Omit<\n React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>,\n 'className' | 'css'\n > {\n name: keyof KnownIconType\n scale?: 1 | 2 | 3 | '1' | '2' | '3'\n 'unsafe-non-guideline-scale'?: number | string\n\n // CustomElements は className が使えない。class と書く必要がある\n // https://ja.reactjs.org/docs/web-components.html#using-web-components-in-react\n class?: string\n}\n\ntype ExtendedIconFile = Exclude<keyof KnownIconType, KnownIconFile>\ntype Extended = [ExtendedIconFile] extends [never] // NOTE: ExtendedIconFileがneverならKnownIconTypeは拡張されていない\n ? false\n : true\n\nexport class PixivIcon extends HTMLElement {\n static readonly tagName = 'pixiv-icon'\n\n static extend(\n map: Extended extends true\n ? Record<ExtendedIconFile, string>\n : Record<string, string>\n ) {\n warning(!__SERVER__, 'Using `PixivIcon.extend()` on server has no effect')\n if (__SERVER__) {\n return\n }\n\n Object.entries(map).forEach(([name, filePathOrUrl]) => {\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n addCustomIcon(name, filePathOrUrl)\n })\n }\n\n static get observedAttributes() {\n return attributes\n }\n\n private svgContent?: string\n private observer?: IntersectionObserver\n private isVisible = false\n\n get props() {\n const partial = Object.fromEntries(\n attributes.map((attribute) => [attribute, this.getAttribute(attribute)])\n ) as Record<(typeof attributes)[number], string | null>\n\n const name = partial.name\n\n if (name === null) {\n throw new TypeError('property \"name\" is required.')\n }\n\n if (!name.includes('/')) {\n throw new TypeError(\n `${name} is not a valid icon name. \"name\" must be named like [size]/[Name].`\n )\n }\n\n return {\n ...partial,\n name,\n }\n }\n\n get forceResizedSize() {\n if (this.props['unsafe-non-guideline-scale'] === null) {\n return null\n }\n\n const [size] = this.props.name.split('/')\n const scale = Number(this.props['unsafe-non-guideline-scale'])\n\n switch (size) {\n case 'Inline': {\n return 16 * scale\n }\n\n default: {\n return Number(size) * scale\n }\n }\n }\n\n get scaledSize() {\n const [size] = this.props.name.split('/')\n\n const scale = Number(this.props.scale ?? '1')\n\n switch (size) {\n case 'Inline': {\n switch (scale) {\n case 2: {\n return 32\n }\n\n default: {\n return 16\n }\n }\n }\n\n case '24': {\n return Number(size) * scale\n }\n\n default: {\n return Number(size)\n }\n }\n }\n\n constructor() {\n super()\n this.attachShadow({ mode: 'open' })\n }\n\n async connectedCallback() {\n this.render()\n await this.waitUntilVisible()\n this.isVisible = true\n await this.loadSvg(this.props.name)\n }\n\n disconnectedCallback() {\n this.observer?.disconnect()\n this.observer = undefined\n this.isVisible = false\n }\n\n attributeChangedCallback(\n attr: string,\n _oldValue: string | null,\n newValue: string\n ) {\n // 非表示の場合はロードしない\n if (!this.isVisible) {\n return\n }\n\n // name が変更された場合必ず再読み込みを試みる\n if (attr === 'name') {\n void this.loadSvg(newValue)\n return\n }\n\n // SVG が読み込み済み && scale などの変更だけならそこだけ反映すればいい\n if (this.svgContent !== undefined) {\n this.render()\n return\n }\n\n // まだ SVG が読み込めてないなら load\n void this.loadSvg(this.props.name)\n }\n\n render() {\n const size = this.forceResizedSize ?? this.scaledSize\n\n const style = DOMPurify.sanitize(\n `<style>\n :host {\n display: inline-flex;\n --size: ${size}px;\n }\n\n svg {\n width: var(--size);\n height: var(--size);\n }\n</style>`,\n { ALLOWED_TAGS: ['style'], FORCE_BODY: true }\n )\n\n const svg = DOMPurify.sanitize(\n this.svgContent !== undefined\n ? this.svgContent\n : `<svg viewBox=\"0 0 ${size} ${size}\"></svg>`,\n { USE_PROFILES: { svg: true, svgFilters: true } }\n )\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.shadowRoot!.innerHTML = style + svg\n }\n\n private async loadSvg(name: string) {\n this.svgContent = await getIcon(name)\n this.render()\n }\n\n private waitUntilVisible() {\n return new Promise<void>((resolve) => {\n this.observer = new IntersectionObserver(\n (entries) => {\n // In Chromium based browsers, multiple entries can be returned even only observe once.\n // Here, we don't care about the entry time but only if isIntersecting happened.\n const isIntersecting = entries.some((entry) => entry.isIntersecting)\n if (isIntersecting) {\n this.observer?.disconnect()\n this.observer = undefined\n resolve()\n }\n },\n { rootMargin: `${ROOT_MARGIN}px` }\n )\n\n this.observer.observe(this)\n })\n }\n}\n","import charcoalIconFiles from '@charcoal-ui/icon-files'\n\nexport default charcoalIconFiles\nexport type KnownIconFile = keyof typeof charcoalIconFiles\nexport const KNOWN_ICON_FILES = Object.keys(\n charcoalIconFiles\n) as KnownIconFile[]\n\nexport function isKnownIconFile(name: string): name is KnownIconFile {\n return name in charcoalIconFiles\n}\n","export class PixivIconLoadError extends Error {\n constructor(name: string, cause: unknown) {\n const message = formatMessage(name, cause)\n\n super(message, { cause })\n this.name = 'PixivIconLoadError'\n Object.setPrototypeOf(this, new.target.prototype)\n }\n}\n\nfunction formatMessage(name: string, cause: unknown) {\n const message = `Failed to fetch <pixiv-icon name=\"${name}\">`\n if (cause == null) {\n return message\n }\n\n if (cause instanceof Error) {\n return `${message}: ${cause.toString()})`\n }\n\n return `${message}: ${JSON.stringify(cause)})`\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\nimport charcoalIconFiles, { KnownIconFile } from '../charcoalIconFiles'\n\n/**\n * `@charcoal-ui/icon-files` に収録されているアイコンを取ってくる\n */\nexport class CharcoalIconFilesLoader implements Loadable {\n private _name: KnownIconFile\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: KnownIconFile) {\n this._name = name\n }\n\n get importIconFile() {\n return charcoalIconFiles[this._name]\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = this.importIconFile()\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { PixivIconLoadError } from './PixivIconLoadError'\nimport { Loadable } from './Loadable'\n\n/**\n * `PixivIcon.extend()` で登録されたカスタムのアイコンを取得する\n */\nexport class CustomIconLoader implements Loadable {\n private _name: string\n private _filePathOrUrl: string\n private _resultSvg: string | undefined = undefined\n private _promise: Promise<string> | undefined = undefined\n\n constructor(name: string, filePathOrUrl: string) {\n this._name = name\n this._filePathOrUrl = filePathOrUrl\n }\n\n async fetch(): Promise<string> {\n if (this._resultSvg !== undefined) {\n return this._resultSvg\n }\n\n if (this._promise) {\n return this._promise\n }\n\n this._promise = fetch(this._filePathOrUrl)\n .then((response) => {\n if (!response.ok) {\n throw new PixivIconLoadError(this._name, 'Response is not ok')\n }\n\n return response.text()\n })\n .then((svg) => {\n this._resultSvg = svg\n return this._resultSvg\n })\n .catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n throw new PixivIconLoadError(this._name, e)\n })\n .finally(() => {\n this._promise = undefined\n })\n\n return this._promise\n }\n}\n","import { isKnownIconFile } from '../charcoalIconFiles'\nimport { CharcoalIconFilesLoader } from './CharcoalIconFilesLoader'\nimport { CustomIconLoader } from './CustomIconLoader'\nimport { Loadable } from './Loadable'\nimport { PixivIconLoadError } from './PixivIconLoadError'\n\n/**\n * icon をロードするオブジェクトのプール。Loader のインスタンスは作り次第ここに入れる\n *\n * 同じアイコンへの複数回のリクエストが起きないためには、Loader がこの中でユニークでないと行けない\n */\nconst loaders = new Map<string, Loadable>()\n\nexport function addCustomIcon(name: string, filePathOrUrl: string) {\n loaders.set(name, new CustomIconLoader(name, filePathOrUrl))\n}\n\nexport async function getIcon(name: string) {\n const loader = resolveIconLoader(name)\n if (loader == null) {\n throw new PixivIconLoadError(name, 'Loader was not found')\n }\n\n return loader.fetch().catch((e) => {\n if (e instanceof PixivIconLoadError) {\n throw e\n }\n\n throw new PixivIconLoadError(name, e)\n })\n}\n\nfunction resolveIconLoader(name: string) {\n // 登録済み or キャッシュ済みの場合\n // addCustomIcon で登録された CustomIconLoader は常にこっちを通る\n const registeredLoader = loaders.get(name)\n if (registeredLoader) {\n return registeredLoader\n }\n\n // `@charcoal-ui/icon-files` に収録されているアイコンにはこれを返す\n if (isKnownIconFile(name)) {\n const charcoalIconFilesLoader = new CharcoalIconFilesLoader(name)\n\n loaders.set(name, charcoalIconFilesLoader)\n return charcoalIconFilesLoader\n }\n\n // 存在しないアイコンにはこれを返す\n return null\n}\n","export const __SERVER__ = typeof window === 'undefined'\n\nconst CAN_USE_DOM = typeof HTMLElement !== 'undefined'\n\n// Workaround: `extends HTMLElement` の形式でないとbabelのトランスパイルがおかしくなる\nif (__SERVER__ || !CAN_USE_DOM) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any\n globalThis.HTMLElement = class {} as any\n}\n","import { PixivIcon, Props } from './PixivIcon'\nimport { __SERVER__ } from './ssr'\nexport { PixivIcon, type KnownIconType, type Props } from './PixivIcon'\nexport { KNOWN_ICON_FILES } from './charcoalIconFiles'\nexport { PixivIconLoadError } from './loaders/PixivIconLoadError'\n\ndeclare global {\n interface Window {\n PixivIcon: typeof PixivIcon\n }\n\n // eslint-disable-next-line @typescript-eslint/no-namespace\n export namespace JSX {\n interface IntrinsicElements {\n 'pixiv-icon': Props\n }\n }\n}\n\nif (!__SERVER__) {\n // TODO: HMR対応\n if (!window.customElements.get(PixivIcon.tagName)) {\n window.PixivIcon = PixivIcon\n window.customElements.define(PixivIcon.tagName, PixivIcon)\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -8,7 +8,7 @@ export declare class CharcoalIconFilesLoader implements Loadable {
|
|
|
8
8
|
private _resultSvg;
|
|
9
9
|
private _promise;
|
|
10
10
|
constructor(name: KnownIconFile);
|
|
11
|
-
get importIconFile(): (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>);
|
|
11
|
+
get importIconFile(): (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>) | (() => Promise<string>);
|
|
12
12
|
fetch(): Promise<string>;
|
|
13
13
|
}
|
|
14
14
|
//# sourceMappingURL=CharcoalIconFilesLoader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CharcoalIconFilesLoader.d.ts","sourceRoot":"","sources":["../../src/loaders/CharcoalIconFilesLoader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAA0B,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEvE;;GAEG;AACH,qBAAa,uBAAwB,YAAW,QAAQ;IACtD,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,QAAQ,CAAyC;gBAE7C,IAAI,EAAE,aAAa;IAI/B,IAAI,cAAc,
|
|
1
|
+
{"version":3,"file":"CharcoalIconFilesLoader.d.ts","sourceRoot":"","sources":["../../src/loaders/CharcoalIconFilesLoader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,OAA0B,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEvE;;GAEG;AACH,qBAAa,uBAAwB,YAAW,QAAQ;IACtD,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,UAAU,CAAgC;IAClD,OAAO,CAAC,QAAQ,CAAyC;gBAE7C,IAAI,EAAE,aAAa;IAI/B,IAAI,cAAc,gyNAEjB;IAEK,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;CAuB/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@charcoal-ui/icons",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.14.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"typescript": "^4.9.5"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@charcoal-ui/icon-files": "^3.
|
|
36
|
+
"@charcoal-ui/icon-files": "^3.14.0",
|
|
37
37
|
"dompurify": "^2.3.6",
|
|
38
38
|
"warning": "^4.0.3"
|
|
39
39
|
},
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"url": "https://github.com/pixiv/charcoal.git",
|
|
51
51
|
"directory": "packages/icons"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "694af78ad36f1caa108a4c3fae4f51ce54b7f78b"
|
|
54
54
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Meta, Story, Canvas, Props } from '@storybook/addon-docs'
|
|
2
|
+
|
|
3
|
+
<Meta title="icons/Custom" />
|
|
4
|
+
|
|
5
|
+
# 独自のアイコンを登録する
|
|
6
|
+
|
|
7
|
+
`<pixiv-icon>` の `name` に存在しない SVG をアイコンとして登録することができます。
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { PixivIcon } from '@charcoal-ui/icons'
|
|
11
|
+
import NewFeature from './icons/16/NewFeature.svg'
|
|
12
|
+
|
|
13
|
+
PixivIcon.extend({
|
|
14
|
+
'16/NewFeature': require('./icons/16/NewFeature.svg'),
|
|
15
|
+
'24/NewFeature': 'https://example.com/hoge.svg',
|
|
16
|
+
'32/NewFeature': NewFeature,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
declare module '@charcoal-ui/icons' {
|
|
20
|
+
export interface KnownIconType {
|
|
21
|
+
'16/NewFeature': unknown
|
|
22
|
+
'24/NewFeature': unknown
|
|
23
|
+
'32/NewFeature': unknown
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
その場合も名前の形式は `{size}/{name}` である必要があります。
|
|
29
|
+
TypeScript 環境では、`KnownIconType` という型を拡張することで、カスタムアイコンに対しても補完が効くようになります。
|
|
30
|
+
|
|
31
|
+
## 独自アイコンのためのバンドラ設定
|
|
32
|
+
|
|
33
|
+
`PixivIcon.extend()` に渡すオブジェクトはキーがアイコン名、値が SVG ファイルに対するパス名または URL である必要があります(内部的には、ここで渡した文字列に対して `fetch()` が走ります)。
|
|
34
|
+
|
|
35
|
+
SVG ファイルを `import` して渡す場合、プロジェクトのバンドラが `*.svg` を **パス文字列として**(ファイルの内容の文字列ではなく)ロードする設定になっていることを確認してください。
|
|
36
|
+
|
|
37
|
+
例えば Webpack の場合、当該アイコンファイルに対するルールの type は [`asset/resource`](https://webpack.js.org/guides/asset-modules/) であるべきです。
|
|
38
|
+
[svgr](https://react-svgr.com/) など、SVG ファイルを文字列以外の値にトランスフォームするツールを使っているプロジェクトでは、`PixivIcon.extend()` に渡す用の `*.svg` ファイルをその対象から除いてください。
|
package/src/PixivIcon.test.tsx
CHANGED
package/src/PixivIcon.ts
CHANGED
|
@@ -213,8 +213,11 @@ export class PixivIcon extends HTMLElement {
|
|
|
213
213
|
private waitUntilVisible() {
|
|
214
214
|
return new Promise<void>((resolve) => {
|
|
215
215
|
this.observer = new IntersectionObserver(
|
|
216
|
-
(
|
|
217
|
-
|
|
216
|
+
(entries) => {
|
|
217
|
+
// In Chromium based browsers, multiple entries can be returned even only observe once.
|
|
218
|
+
// Here, we don't care about the entry time but only if isIntersecting happened.
|
|
219
|
+
const isIntersecting = entries.some((entry) => entry.isIntersecting)
|
|
220
|
+
if (isIntersecting) {
|
|
218
221
|
this.observer?.disconnect()
|
|
219
222
|
this.observer = undefined
|
|
220
223
|
resolve()
|
package/src/README.mdx
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Meta, Story, Canvas, Props } from '@storybook/addon-docs'
|
|
2
|
+
|
|
3
|
+
<Meta title="icons/README" />
|
|
4
|
+
|
|
5
|
+
# @charcoal-ui/icons クイックスタート
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@charcoal-ui/icons)
|
|
8
|
+
|
|
9
|
+
## インストール
|
|
10
|
+
|
|
11
|
+
以下のいずれかのパッケージマネージャーを使用してインストールしてください
|
|
12
|
+
|
|
13
|
+
### npm
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @charcoal-ui/icons
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### yarn
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add @charcoal-ui/icons
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### pnpm
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm add @charcoal-ui/icons
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### bun
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bun add @charcoal-ui/icons
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 概要
|
|
38
|
+
|
|
39
|
+
`@charcoal-ui/icons` は、SVG アイコンを [Web Components](https://developer.mozilla.org/ja/docs/Web/API/Web_components) の [Custom Elements](https://developer.mozilla.org/ja/docs/Web/API/Web_components/Using_custom_elements) として利用できるライブラリです。
|
|
40
|
+
|
|
41
|
+
## 使い方
|
|
42
|
+
|
|
43
|
+
アプリケーションのエントリポイントで `import` します。
|
|
44
|
+
Storybook の場合は `preview.(js|ts)` に書くと良いでしょう。
|
|
45
|
+
|
|
46
|
+
**`@charcoal-ui/react` の [`<Icon>`](/docs/react-icon--docs) コンポーネントを利用している場合、この `import` は内部で自動的に行われます。**
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import '@charcoal-ui/icons'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
これだけで、`<pixiv-icon>` という HTML タグが利用可能になります。
|
|
53
|
+
TypeScript の型定義がグローバルにインストールされるので、JSX で `<pixiv-icon>` を書く際にも型チェックが効きます。
|
|
54
|
+
|
|
55
|
+
## 収録アイコン
|
|
56
|
+
|
|
57
|
+
[PixivIcon](/docs/icons-pixivicon-pixiv-icon--docs) のページを見てください。
|
|
58
|
+
|
|
59
|
+
## 各種バンドラとの組み合わせ
|
|
60
|
+
|
|
61
|
+
`@charcoal-ui/icons@v2.0.0` 以前、このライブラリはアイコンを `.svg` ファイルとしてエクスポートしていました。
|
|
62
|
+
したがって、利用の際は各種バンドラで `.svg` ファイルを `import` できるように設定ファイルを変更する必要がありました。
|
|
63
|
+
|
|
64
|
+
`v2.0.0` 以降、アイコンは JavaScript の文字列としてエクスポートされるようになっています。
|
|
65
|
+
したがって、`@charcoal-ui/icons` に収録されたアイコンを利用するだけなら、バンドラの設定は必要ありません。
|
|
66
|
+
|
|
67
|
+
プロジェクト内の SVG ファイルをアイコンとして登録したい場合は、[必要に応じて .svg を import できるように設定してください](/docs/icons-custom-icon--docs)。
|
|
68
|
+
|
|
69
|
+
## React と組み合わせて使う
|
|
70
|
+
|
|
71
|
+
`@charcoal-ui/react` に `<Icon>` コンポーネントが収録されているので、基本的にはそちらを利用してください。
|
|
72
|
+
|
|
73
|
+
### `@charcoal-ui/react` を使わない場合
|
|
74
|
+
|
|
75
|
+
Custom Element は `className` という props を受け取ることが通常できません。
|
|
76
|
+
|
|
77
|
+
> Custom elements accept `class` rather than `className`, and `for` rather than `htmlFor`.
|
|
78
|
+
> [React 公式ドキュメントより](https://reactjs.org/docs/web-components.html#using-web-components-in-react)
|
|
79
|
+
|
|
80
|
+
もし `styled-components` などを使っていて `className` を渡せないと困るケースでは、ラッパーコンポーネントを作ることができます。
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { Props as IconProps } from '@charcoal-ui/icons'
|
|
84
|
+
|
|
85
|
+
interface Props extends Omit<IconProps, 'class'> {
|
|
86
|
+
className?: string
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const Icon: React.FC<Props> = ({ className, ...props }) => (
|
|
90
|
+
<pixiv-icon class={className} {...props} />
|
|
91
|
+
)
|
|
92
|
+
```
|
package/src/SSR.mdx
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Meta, Story, Canvas, Props } from '@storybook/addon-docs'
|
|
2
|
+
|
|
3
|
+
<Meta title="icons/SSR Guide" />
|
|
4
|
+
|
|
5
|
+
# サーバーサイドレンダリング
|
|
6
|
+
|
|
7
|
+
`<pixiv-icon>` はサーバーサイドレンダリング時にも利用できます。
|
|
8
|
+
`@charcoal-ui/icons` は、Node.js の環境下で import されたり、API を呼び出されても問題が起きないように設計されています。
|
|
9
|
+
|
|
10
|
+
一方、Custom Element であるということは、**SVG アイコンの読み込みはクライアントサイドで行われます**。
|
|
11
|
+
したがって、大きさが確定せずにレイアウトシフトが起こりうるのは、SSR における注意点の一つと言えます。
|
|
12
|
+
|
|
13
|
+
以下のようなコードをリセット CSS に含めることで、`<pixiv-icon>` によるレイアウトシフトの発生を防ぐことができます。
|
|
14
|
+
(簡単のため、ネスト記法が利用できるケースを意図しています)
|
|
15
|
+
|
|
16
|
+
```css
|
|
17
|
+
pixiv-icon {
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
width: calc(var(--icon-size, 1em) * var(--scale, 1));
|
|
20
|
+
height: calc(var(--icon-size, 1em) * var(--scale, 1));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&[name~='16/'] {
|
|
24
|
+
--icon-size: 16px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&[name~='24/'] {
|
|
28
|
+
--icon-size: 24px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&[name~='32/'] {
|
|
32
|
+
--icon-size: 32px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&[scale='2'] {
|
|
36
|
+
--scale: 2;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&[scale='3'] {
|
|
40
|
+
--scale: 3;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* NOTICE: 現状と attr(... number) ほぼ変とのブラウザも少ない */
|
|
44
|
+
&[unsafe-non-guideline-scale] {
|
|
45
|
+
--scale: attr(unsafe-non-guideline-scale number);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
ただしコメントにもある通り、**現状 `unsafe-non-guideline-scale` をつけた要素は、リセット CSS だけではレイアウトシフトが防げません。**
|
|
50
|
+
CSS の `attr()` が数値の解釈をサポートするまで、個別にインラインスタイルを用いて大きさを確定させるなどのワークアラウンドが必要です。
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<pixiv-icon
|
|
54
|
+
name="24/Add"
|
|
55
|
+
unsafe-non-guideline-scale="0.5"
|
|
56
|
+
style="--scale: 0.5;"
|
|
57
|
+
></pixiv-icon>
|
|
58
|
+
<pixiv-icon
|
|
59
|
+
name="24/Add"
|
|
60
|
+
unsafe-non-guideline-scale="0.5"
|
|
61
|
+
style="width: 12px; height: 12px;"
|
|
62
|
+
></pixiv-icon>
|
|
63
|
+
```
|