@elmethis/qwik 1.0.0-alpha.27 → 1.0.0-alpha.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1",
3
- "manifestHash": "hmurka",
3
+ "manifestHash": "w0o7qg",
4
4
  "options": {
5
5
  "target": "lib",
6
6
  "buildMode": "development",
@@ -30,8 +30,8 @@
30
30
  "mapping": {},
31
31
  "bundles": {
32
32
  "../index.qwik.cjs": {
33
- "size": 467302,
34
- "total": 467302,
33
+ "size": 489408,
34
+ "total": 489408,
35
35
  "origins": [
36
36
  "src/components/a2ui/catalog/basic-catalog.tsx",
37
37
  "src/components/a2ui/catalog/block-catalog.tsx",
@@ -115,6 +115,8 @@
115
115
  "src/components/icon/elm-toggle-theme.module.css",
116
116
  "src/components/icon/elm-toggle-theme.tsx",
117
117
  "src/components/icon/language-glyph.tsx",
118
+ "src/components/media/elm-audio-player.module.css",
119
+ "src/components/media/elm-audio-player.tsx",
118
120
  "src/components/media/elm-block-image.module.css",
119
121
  "src/components/media/elm-block-image.tsx",
120
122
  "src/components/media/elm-file.module.css",
@@ -185,7 +187,7 @@
185
187
  "assets": {
186
188
  "style.css": {
187
189
  "name": "style.css.css",
188
- "size": 69011
190
+ "size": 79234
189
191
  },
190
192
  "assets/bundle-graph.BqrDAOEV.json": {
191
193
  "name": "bundle-graph.json",
package/lib/style.css CHANGED
@@ -761,6 +761,453 @@
761
761
  color: var(--elmethis-color-primary);
762
762
  }
763
763
  }
764
+ ._elm-audio-player_p7xym_1 {
765
+ box-sizing: border-box;
766
+ width: 100%;
767
+ margin-block-start: var(--elmethis-margin-block-start);
768
+ padding: 0.875rem 1.5rem;
769
+ display: flex;
770
+ flex-direction: column;
771
+ gap: 0.75rem;
772
+ position: relative;
773
+ overflow: hidden;
774
+ border: 1px solid var(--elmethis-color-surface-sunken);
775
+ border-radius: 0.75rem;
776
+ background-color: var(--elmethis-color-surface-raised);
777
+ user-select: none;
778
+ }
779
+
780
+ /* Hairline accent that warms as playback advances. */
781
+ ._elm-audio-player_p7xym_1::before {
782
+ content: "";
783
+ position: absolute;
784
+ inset: 0 0 auto;
785
+ height: 1px;
786
+ background: linear-gradient(
787
+ 90deg,
788
+ var(--elmethis-color-primary)
789
+ calc(var(--elmethis-scoped-progress, 0) * 100%),
790
+ var(--elmethis-color-neutral-weak)
791
+ calc(var(--elmethis-scoped-progress, 0) * 100%)
792
+ );
793
+ opacity: 0.5;
794
+ transition: opacity 300ms ease;
795
+ }
796
+
797
+ ._elm-audio-player_p7xym_1._loading_p7xym_34::before {
798
+ opacity: 0.3;
799
+ }
800
+
801
+ /* ---- Header ------------------------------------------------------------- */
802
+
803
+ ._header_p7xym_40 {
804
+ display: flex;
805
+ align-items: center;
806
+ gap: 0.75rem;
807
+ }
808
+
809
+ ._artwork_p7xym_46 {
810
+ flex: 0 0 auto;
811
+ display: grid;
812
+ place-items: center;
813
+ width: 2.5rem;
814
+ height: 2.5rem;
815
+ border-radius: 0.5rem;
816
+ color: var(--elmethis-color-surface-raised);
817
+ background: linear-gradient(
818
+ 145deg,
819
+ var(--elmethis-color-primary-strong),
820
+ var(--elmethis-color-primary)
821
+ );
822
+ box-shadow: 0 0.25rem 0.5rem -0.25rem var(--elmethis-box-shadow-color);
823
+ }
824
+
825
+ /* Error: the artwork tile turns into a red alert badge. */
826
+ ._artwork-error_p7xym_63 {
827
+ color: var(--elmethis-color-accent-error);
828
+ background: var(--elmethis-color-accent-error-surface);
829
+ box-shadow: none;
830
+ }
831
+
832
+ ._meta_p7xym_69 {
833
+ flex: 1 1 auto;
834
+ min-width: 0;
835
+ display: flex;
836
+ flex-direction: column;
837
+ gap: 0.125rem;
838
+ }
839
+
840
+ ._title_p7xym_77 {
841
+ overflow: hidden;
842
+ font-size: 0.95rem;
843
+ font-weight: 600;
844
+ letter-spacing: 0.01em;
845
+ color: var(--elmethis-color-neutral-strong);
846
+ white-space: nowrap;
847
+ text-overflow: ellipsis;
848
+ }
849
+
850
+ ._artist_p7xym_87 {
851
+ overflow: hidden;
852
+ font-family: var(--elmethis-font-family-monospace);
853
+ font-size: 0.7rem;
854
+ letter-spacing: 0.06em;
855
+ text-transform: uppercase;
856
+ color: var(--elmethis-color-neutral);
857
+ white-space: nowrap;
858
+ text-overflow: ellipsis;
859
+ }
860
+
861
+ /* Now-playing equalizer — four bars that only dance while live. */
862
+ ._equalizer_p7xym_99 {
863
+ flex: 0 0 auto;
864
+ display: flex;
865
+ align-items: flex-end;
866
+ gap: 2px;
867
+ width: 1.25rem;
868
+ height: 1.25rem;
869
+
870
+ i {
871
+ flex: 1;
872
+ height: 25%;
873
+ border-radius: 1px;
874
+ background-color: var(--elmethis-color-neutral-weak);
875
+ transition: background-color 300ms ease;
876
+ }
877
+ }
878
+
879
+ ._playing_p7xym_116 ._equalizer_p7xym_99 i {
880
+ background-color: var(--elmethis-color-primary);
881
+ animation: _elm-eq_p7xym_1 900ms ease-in-out infinite;
882
+ }
883
+
884
+ ._playing_p7xym_116 ._equalizer_p7xym_99 i:nth-child(1) {
885
+ animation-delay: -200ms;
886
+ }
887
+
888
+ ._playing_p7xym_116 ._equalizer_p7xym_99 i:nth-child(2) {
889
+ animation-delay: -600ms;
890
+ }
891
+
892
+ ._playing_p7xym_116 ._equalizer_p7xym_99 i:nth-child(3) {
893
+ animation-delay: -100ms;
894
+ }
895
+
896
+ ._playing_p7xym_116 ._equalizer_p7xym_99 i:nth-child(4) {
897
+ animation-delay: -450ms;
898
+ }
899
+
900
+ @keyframes _elm-eq_p7xym_1 {
901
+ 0%,
902
+ 100% {
903
+ height: 22%;
904
+ }
905
+
906
+ 50% {
907
+ height: 100%;
908
+ }
909
+ }
910
+
911
+ /* ---- Seek line ---------------------------------------------------------- */
912
+
913
+ /* A roomy hit area so the thin line stays easy to grab. */
914
+ ._seekbar_p7xym_151 {
915
+ position: relative;
916
+ width: 100%;
917
+ height: 1.25rem;
918
+ display: flex;
919
+ align-items: center;
920
+ cursor: pointer;
921
+ touch-action: none;
922
+ }
923
+
924
+ ._seekbar_p7xym_151:focus-visible {
925
+ outline: 2px solid var(--elmethis-color-primary);
926
+ outline-offset: 4px;
927
+ border-radius: 0.25rem;
928
+ }
929
+
930
+ ._track_p7xym_167 {
931
+ position: relative;
932
+ width: 100%;
933
+ height: 0.25rem;
934
+ border-radius: 999px;
935
+ background-color: var(--elmethis-color-neutral-weak);
936
+ overflow: hidden;
937
+ }
938
+
939
+ ._fill_p7xym_176 {
940
+ position: absolute;
941
+ inset: 0 auto 0 0;
942
+ width: calc(var(--elmethis-scoped-progress, 0) * 100%);
943
+ border-radius: 999px;
944
+ background-color: var(--elmethis-color-primary);
945
+ }
946
+
947
+ ._playing_p7xym_116 ._fill_p7xym_176 {
948
+ box-shadow: 0 0 0.375rem 0 var(--elmethis-color-primary);
949
+ }
950
+
951
+ /* Draggable handle, parked at the play position. */
952
+ ._thumb_p7xym_189 {
953
+ position: absolute;
954
+ top: 50%;
955
+ left: calc(var(--elmethis-scoped-progress, 0) * 100%);
956
+ width: 0.75rem;
957
+ height: 0.75rem;
958
+ border-radius: 50%;
959
+ background-color: var(--elmethis-color-primary-strong);
960
+ box-shadow: 0 0.125rem 0.375rem -0.0625rem var(--elmethis-box-shadow-color);
961
+ transform: translate(-50%, -50%);
962
+ transition: transform 140ms cubic-bezier(0.34, 1.56, 0.64, 1);
963
+ pointer-events: none;
964
+ }
965
+
966
+ ._seekbar_p7xym_151:hover ._thumb_p7xym_189,
967
+ ._seekbar_p7xym_151:focus-visible ._thumb_p7xym_189 {
968
+ transform: translate(-50%, -50%) scale(1.25);
969
+ }
970
+
971
+ /* Faint marker that tracks the cursor on hover. */
972
+ ._hover-thumb_p7xym_209 {
973
+ position: absolute;
974
+ top: 50%;
975
+ left: calc(var(--elmethis-scoped-hover, 0) * 100%);
976
+ width: 0.625rem;
977
+ height: 0.625rem;
978
+ border-radius: 50%;
979
+ background-color: var(--elmethis-color-primary);
980
+ opacity: 0;
981
+ transform: translate(-50%, -50%);
982
+ transition: opacity 160ms ease;
983
+ pointer-events: none;
984
+ }
985
+
986
+ ._seekbar_p7xym_151:hover ._hover-thumb_p7xym_209 {
987
+ opacity: 0.35;
988
+ }
989
+
990
+ ._loading_p7xym_34 ._seekbar_p7xym_151 {
991
+ cursor: progress;
992
+ }
993
+
994
+ ._loading_p7xym_34 ._track_p7xym_167 {
995
+ animation: _elm-pulse_p7xym_1 1.4s ease-in-out infinite;
996
+ }
997
+
998
+ @keyframes _elm-pulse_p7xym_1 {
999
+ 0%,
1000
+ 100% {
1001
+ opacity: 0.55;
1002
+ }
1003
+
1004
+ 50% {
1005
+ opacity: 1;
1006
+ }
1007
+ }
1008
+
1009
+ /* ---- Controls ----------------------------------------------------------- */
1010
+
1011
+ ._controls_p7xym_248 {
1012
+ display: flex;
1013
+ align-items: center;
1014
+ gap: 0.75rem;
1015
+ }
1016
+
1017
+ ._time_p7xym_254 {
1018
+ flex: 0 0 auto;
1019
+ min-width: 3ch;
1020
+ font-family: var(--elmethis-font-family-monospace);
1021
+ font-size: 0.75rem;
1022
+ font-variant-numeric: tabular-nums;
1023
+ letter-spacing: 0.03em;
1024
+ color: var(--elmethis-color-neutral);
1025
+ }
1026
+
1027
+ ._time-current_p7xym_264 {
1028
+ color: var(--elmethis-color-primary);
1029
+ text-align: left;
1030
+ }
1031
+
1032
+ ._time-total_p7xym_269 {
1033
+ text-align: right;
1034
+ }
1035
+
1036
+ ._transport_p7xym_273 {
1037
+ flex: 1 1 auto;
1038
+ display: flex;
1039
+ align-items: center;
1040
+ justify-content: center;
1041
+ gap: 0.5rem;
1042
+ }
1043
+
1044
+ ._icon-button_p7xym_281 {
1045
+ display: grid;
1046
+ place-items: center;
1047
+ width: 2rem;
1048
+ height: 2rem;
1049
+ padding: 0;
1050
+ border: none;
1051
+ border-radius: 50%;
1052
+ color: var(--elmethis-color-neutral-strong);
1053
+ background: transparent;
1054
+ cursor: pointer;
1055
+ transition:
1056
+ color 160ms ease,
1057
+ background-color 160ms ease,
1058
+ transform 120ms ease;
1059
+ }
1060
+
1061
+ ._icon-button_p7xym_281:hover {
1062
+ color: var(--elmethis-color-primary);
1063
+ background-color: var(--elmethis-color-primary-hover);
1064
+ }
1065
+
1066
+ ._icon-button_p7xym_281:active {
1067
+ transform: scale(0.92);
1068
+ }
1069
+
1070
+ ._icon-button_p7xym_281:focus-visible {
1071
+ outline: 2px solid var(--elmethis-color-primary);
1072
+ outline-offset: 2px;
1073
+ }
1074
+
1075
+ ._play-button_p7xym_312 {
1076
+ display: grid;
1077
+ place-items: center;
1078
+ width: 3rem;
1079
+ height: 3rem;
1080
+ padding: 0;
1081
+ border: none;
1082
+ border-radius: 50%;
1083
+ color: var(--elmethis-color-surface-raised);
1084
+ background: linear-gradient(
1085
+ 145deg,
1086
+ var(--elmethis-color-primary-strong),
1087
+ var(--elmethis-color-primary)
1088
+ );
1089
+ cursor: pointer;
1090
+ box-shadow:
1091
+ 0 0 0 1px color-mix(in srgb, var(--elmethis-color-primary) 40%, transparent),
1092
+ 0 0.375rem 0.875rem -0.375rem var(--elmethis-color-primary);
1093
+ transition:
1094
+ transform 140ms cubic-bezier(0.34, 1.56, 0.64, 1),
1095
+ box-shadow 160ms ease;
1096
+ }
1097
+
1098
+ ._play-button_p7xym_312:hover {
1099
+ transform: scale(1.06);
1100
+ box-shadow:
1101
+ 0 0 0 1px color-mix(in srgb, var(--elmethis-color-primary) 60%, transparent),
1102
+ 0 0.5rem 1.25rem -0.375rem var(--elmethis-color-primary);
1103
+ }
1104
+
1105
+ ._play-button_p7xym_312:active {
1106
+ transform: scale(0.96);
1107
+ }
1108
+
1109
+ ._play-button_p7xym_312:focus-visible {
1110
+ outline: 2px solid var(--elmethis-color-primary-strong);
1111
+ outline-offset: 3px;
1112
+ }
1113
+
1114
+ ._playing_p7xym_116 ._play-button_p7xym_312 {
1115
+ box-shadow:
1116
+ 0 0 0 1px color-mix(in srgb, var(--elmethis-color-primary) 50%, transparent),
1117
+ 0 0 0 6px var(--elmethis-color-primary-hover);
1118
+ }
1119
+
1120
+ /* ---- Volume ------------------------------------------------------------- */
1121
+
1122
+ ._volume_p7xym_359 {
1123
+ flex: 0 0 auto;
1124
+ display: flex;
1125
+ align-items: center;
1126
+ gap: 0.25rem;
1127
+ }
1128
+
1129
+ ._volume-slider_p7xym_366 {
1130
+ width: 0;
1131
+ height: 0.25rem;
1132
+ margin: 0;
1133
+ padding: 0;
1134
+ opacity: 0;
1135
+ appearance: none;
1136
+ border-radius: 999px;
1137
+ background: linear-gradient(
1138
+ 90deg,
1139
+ var(--elmethis-color-primary) calc(var(--elmethis-scoped-volume, 1) * 100%),
1140
+ var(--elmethis-color-neutral-weak)
1141
+ calc(var(--elmethis-scoped-volume, 1) * 100%)
1142
+ );
1143
+ cursor: pointer;
1144
+ transition:
1145
+ width 220ms ease,
1146
+ opacity 220ms ease;
1147
+ }
1148
+
1149
+ ._volume_p7xym_359:hover ._volume-slider_p7xym_366,
1150
+ ._volume_p7xym_359:focus-within ._volume-slider_p7xym_366 {
1151
+ width: 4rem;
1152
+ opacity: 1;
1153
+ }
1154
+
1155
+ ._volume-slider_p7xym_366::-webkit-slider-thumb {
1156
+ appearance: none;
1157
+ width: 0.75rem;
1158
+ height: 0.75rem;
1159
+ border: none;
1160
+ border-radius: 50%;
1161
+ background-color: var(--elmethis-color-primary-strong);
1162
+ box-shadow: 0 0.125rem 0.25rem -0.0625rem var(--elmethis-box-shadow-color);
1163
+ }
1164
+
1165
+ ._volume-slider_p7xym_366::-moz-range-thumb {
1166
+ width: 0.75rem;
1167
+ height: 0.75rem;
1168
+ border: none;
1169
+ border-radius: 50%;
1170
+ background-color: var(--elmethis-color-primary-strong);
1171
+ }
1172
+
1173
+ /* ---- Error -------------------------------------------------------------- */
1174
+
1175
+ ._errored_p7xym_412 {
1176
+ border-color: color-mix(
1177
+ in srgb,
1178
+ var(--elmethis-color-accent-error) 45%,
1179
+ var(--elmethis-color-neutral-weak)
1180
+ );
1181
+ }
1182
+
1183
+ /* Replaces the seek line + transport with a plain, labeled message. */
1184
+ ._error-notice_p7xym_421 {
1185
+ display: flex;
1186
+ align-items: center;
1187
+ gap: 0.5rem;
1188
+ padding: 0.625rem 0.875rem;
1189
+ border-radius: 0.5rem;
1190
+ color: var(--elmethis-color-accent-error);
1191
+ background-color: var(--elmethis-color-accent-error-surface);
1192
+ }
1193
+
1194
+ ._error-message_p7xym_431 {
1195
+ font-size: 0.85rem;
1196
+ font-weight: 500;
1197
+ line-height: 1.3;
1198
+ }
1199
+
1200
+ @media (prefers-reduced-motion: reduce) {
1201
+ ._playing_p7xym_116 ._equalizer_p7xym_99 i,
1202
+ ._loading_p7xym_34 ._track_p7xym_167 {
1203
+ animation: none;
1204
+ }
1205
+
1206
+ ._elm-audio-player_p7xym_1 *,
1207
+ ._elm-audio-player_p7xym_1 {
1208
+ transition-duration: 0.01ms !important;
1209
+ }
1210
+ }
764
1211
  ._elm-block-image_kwjx3_1 {
765
1212
  margin-block-start: var(--elmethis-margin-block-start);
766
1213
  margin-inline: 0;
@@ -13,6 +13,8 @@ export declare const Divider: Story;
13
13
  export declare const Toggle: Story;
14
14
  export declare const Bookmark: Story;
15
15
  export declare const File: Story;
16
+ export declare const Audio: Story;
17
+ export declare const Video: Story;
16
18
  export declare const BlockImage: Story;
17
19
  export declare const CodeBlock: Story;
18
20
  export declare const Katex: Story;
@@ -0,0 +1,37 @@
1
+ import { PropsOf } from "@qwik.dev/core";
2
+ export interface ElmAudioPlayerProps extends Omit<PropsOf<"div">, "title"> {
3
+ /**
4
+ * Audio source URL.
5
+ */
6
+ src: string;
7
+ /**
8
+ * Track title shown in the header. Falls back to the file name in `src`.
9
+ */
10
+ title?: string;
11
+ /**
12
+ * Secondary line under the title (artist, album, podcast name, …).
13
+ */
14
+ artist?: string;
15
+ /**
16
+ * Message shown when the audio fails to load (bad URL, network/CORS error,
17
+ * unsupported codec). Replaces the transport with a labeled alert.
18
+ *
19
+ * @defaultValue "This audio couldn't be loaded."
20
+ */
21
+ errorMessage?: string;
22
+ /**
23
+ * Seconds the skip-back / skip-forward controls jump.
24
+ *
25
+ * @defaultValue 10
26
+ */
27
+ seekStep?: number;
28
+ /**
29
+ * Loop playback when the track ends. Forwarded to the native `<audio>`.
30
+ */
31
+ loop?: boolean;
32
+ /**
33
+ * Begin playing as soon as the audio can. Forwarded to the native `<audio>`.
34
+ */
35
+ autoPlay?: boolean;
36
+ }
37
+ export declare const ElmAudioPlayer: import("@qwik.dev/core").Component<ElmAudioPlayerProps>;
@@ -0,0 +1,11 @@
1
+ import type { Meta, StoryObj } from "storybook-framework-qwik";
2
+ import { type ElmAudioPlayerProps } from "./elm-audio-player";
3
+ declare const meta: Meta<ElmAudioPlayerProps>;
4
+ export default meta;
5
+ type Story = StoryObj<ElmAudioPlayerProps>;
6
+ export declare const Primary: Story;
7
+ export declare const TitleOnly: Story;
8
+ export declare const ArtistOnly: Story;
9
+ export declare const FilenameFallback: Story;
10
+ export declare const BigSeekStep: Story;
11
+ export declare const Errored: Story;
@@ -58,6 +58,7 @@ export { ElmLanguageIcon, type ElmLanguageIconProps, } from "./components/icon/e
58
58
  export { ElmMdiIcon, type ElmMdiIconProps, } from "./components/icon/elm-mdi-icon";
59
59
  export { ElmSquareLoadingIcon, type ElmSquareLoadingIconProps, } from "./components/icon/elm-square-loading-icon";
60
60
  export { ElmToggleTheme, type ElmToggleThemeProps, } from "./components/icon/elm-toggle-theme";
61
+ export { ElmAudioPlayer, type ElmAudioPlayerProps, } from "./components/media/elm-audio-player";
61
62
  export { ElmBlockImage, type ElmBlockImageProps, } from "./components/media/elm-block-image";
62
63
  export { ElmFile, type ElmFileProps } from "./components/media/elm-file";
63
64
  export { ElmBookmark, type ElmBookmarkProps, } from "./components/navigation/elm-bookmark";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elmethis/qwik",
3
- "version": "1.0.0-alpha.27",
3
+ "version": "1.0.0-alpha.29",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -83,7 +83,7 @@
83
83
  "uuid": "^14.0.0",
84
84
  "zod": "^3",
85
85
  "zod-to-json-schema": "^3.25.2",
86
- "@elmethis/core": "^0.11.0"
86
+ "@elmethis/core": "^0.13.0"
87
87
  },
88
88
  "peerDependencies": {
89
89
  "@qwik.dev/core": ">=2.0.0-beta.31"
@@ -104,8 +104,8 @@
104
104
  "test.unit": "vitest --run",
105
105
  "test.browser": "vitest --run --config vitest.browser.config.ts",
106
106
  "test.build": "pnpm run build && pnpm run build-storybook",
107
- "check": "concurrently -g \"pnpm:fmt.check\" \"pnpm:lint\" \"pnpm:lint.css\" \"pnpm:build.types\" \"pnpm:test.unit\" \"pnpm:test.browser\"",
108
- "check.ci": "concurrently -g \"pnpm:check\" \"pnpm:test.build\"",
107
+ "check": "concurrently -g \"pnpm:fmt.check\" \"pnpm:lint\" \"pnpm:lint.css\" \"pnpm:build.types\" \"pnpm:test.unit\"",
108
+ "check.ci": "concurrently -g \"pnpm:check\" \"pnpm:test.build\" \"pnpm:test.browser\"",
109
109
  "qwik": "qwik"
110
110
  }
111
111
  }