@meith/theme-raidframe 0.6.0 → 0.8.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/package.json +4 -4
- package/src/copy.ts +286 -0
- package/src/index.ts +2 -2
- package/src/messages/en.json +144 -0
- package/src/messages/index.ts +5 -0
- package/src/shared.tsx +1 -2
- package/src/slots/announcement.tsx +16 -6
- package/src/slots/auth-page.tsx +12 -3
- package/src/slots/board-index.tsx +10 -3
- package/src/slots/board-stats.tsx +18 -12
- package/src/slots/category-block.tsx +13 -6
- package/src/slots/discovery-view.tsx +17 -8
- package/src/slots/error-notice.tsx +17 -5
- package/src/slots/footer.tsx +16 -4
- package/src/slots/forum-display.tsx +20 -11
- package/src/slots/forum-row.tsx +26 -10
- package/src/slots/header.tsx +13 -3
- package/src/slots/latest-posts.tsx +12 -6
- package/src/slots/latest-threads.tsx +18 -8
- package/src/slots/member-profile.tsx +14 -10
- package/src/slots/navigation.tsx +6 -3
- package/src/slots/notice.tsx +7 -4
- package/src/slots/pagination.tsx +10 -6
- package/src/slots/panel-nav.tsx +40 -13
- package/src/slots/panel-page.tsx +12 -11
- package/src/slots/post-actions.tsx +17 -10
- package/src/slots/post-bit.tsx +29 -18
- package/src/slots/post-form.tsx +14 -4
- package/src/slots/redirect-notice.tsx +16 -8
- package/src/slots/search-form.tsx +12 -8
- package/src/slots/search-results.tsx +26 -16
- package/src/slots/shell.tsx +6 -3
- package/src/slots/subforum-list.tsx +8 -5
- package/src/slots/thread-row.tsx +19 -11
- package/src/slots/thread-view.tsx +22 -8
- package/src/slots/user-panel.tsx +14 -14
- package/src/slots/who-is-online.tsx +19 -10
- package/src/theme.ts +66 -0
package/src/slots/thread-row.tsx
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { ThreadRowSlotModel } from '@meith/theme-kit'
|
|
1
|
+
import type { SlotCopy, ThreadRowSlotModel } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
2
3
|
|
|
3
4
|
import { MICRO, NUMERIC, ReadPip, Stamp, UserRef } from '../shared'
|
|
4
5
|
|
|
5
6
|
const TAG = 'border px-1.5 py-px font-mono text-[0.625rem] font-bold uppercase tracking-[0.12em]'
|
|
6
7
|
|
|
7
|
-
export function ThreadRow({ thread, select }: ThreadRowSlotModel) {
|
|
8
|
+
export function ThreadRow({ thread, select, copy }: ThreadRowSlotModel & { copy: SlotCopy }) {
|
|
9
|
+
const c = (key: string) => fromSlotCopy(copy, `raidframe.threadRow.${key}`)
|
|
10
|
+
|
|
8
11
|
return (
|
|
9
12
|
<tr className="border-t border-border align-top hover:bg-secondary/50">
|
|
10
13
|
<td className="px-3 py-2.5">
|
|
@@ -31,40 +34,45 @@ export function ThreadRow({ thread, select }: ThreadRowSlotModel) {
|
|
|
31
34
|
<a href={thread.href} className="font-medium text-foreground hover:text-primary">
|
|
32
35
|
{thread.title}
|
|
33
36
|
</a>
|
|
34
|
-
{thread.isUnread && <span className="sr-only">(
|
|
37
|
+
{thread.isUnread && <span className="sr-only">{c('newPosts')}</span>}
|
|
35
38
|
|
|
36
39
|
{thread.isSticky && (
|
|
37
|
-
<span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>
|
|
40
|
+
<span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>
|
|
41
|
+
{c('pinned')}
|
|
42
|
+
</span>
|
|
38
43
|
)}
|
|
39
44
|
{thread.isLocked && (
|
|
40
|
-
<span className={`${TAG} border-thread-locked/60 text-thread-locked`}>
|
|
45
|
+
<span className={`${TAG} border-thread-locked/60 text-thread-locked`}>
|
|
46
|
+
{c('locked')}
|
|
47
|
+
</span>
|
|
41
48
|
)}
|
|
42
49
|
{thread.isMoved && (
|
|
43
|
-
<span className={`${TAG} border-thread-moved/60 text-thread-moved`}>moved</span>
|
|
50
|
+
<span className={`${TAG} border-thread-moved/60 text-thread-moved`}>{c('moved')}</span>
|
|
44
51
|
)}
|
|
45
52
|
</div>
|
|
46
53
|
|
|
47
54
|
<p className={`${MICRO} mt-1 normal-case`}>
|
|
48
|
-
<span className="uppercase">
|
|
55
|
+
<span className="uppercase">{c('startedBy')}</span>{' '}
|
|
49
56
|
<UserRef user={thread.author} className="hover:text-primary" />
|
|
50
57
|
</p>
|
|
51
58
|
</td>
|
|
52
59
|
|
|
53
60
|
<td className={`w-16 px-2 py-2.5 text-right text-xs ${NUMERIC} text-foreground`}>
|
|
54
|
-
{thread.replyCount}
|
|
61
|
+
{thread.replyCount.label}
|
|
55
62
|
</td>
|
|
56
63
|
<td className={`w-16 px-2 py-2.5 text-right text-xs ${NUMERIC} text-muted-foreground`}>
|
|
57
|
-
{thread.viewCount}
|
|
64
|
+
{thread.viewCount.label}
|
|
58
65
|
</td>
|
|
59
66
|
|
|
60
67
|
<td className="hidden w-52 px-3 py-2.5 text-xs text-muted-foreground sm:table-cell">
|
|
61
68
|
{thread.lastPost === null ? (
|
|
62
|
-
<span className={MICRO}
|
|
69
|
+
<span className={MICRO}>{c('none')}</span>
|
|
63
70
|
) : (
|
|
64
71
|
<a href={thread.lastPost.href} className="block hover:text-primary">
|
|
65
72
|
<Stamp at={thread.lastPost.at} className="text-foreground" />
|
|
66
73
|
<span className={`${MICRO} mt-0.5 block normal-case`}>
|
|
67
|
-
|
|
74
|
+
{c('byPrefix')}
|
|
75
|
+
<UserRef user={thread.lastPost.author} linked={false} />
|
|
68
76
|
</span>
|
|
69
77
|
</a>
|
|
70
78
|
)}
|
|
@@ -1,14 +1,24 @@
|
|
|
1
|
-
import type { ThreadViewModel } from '@meith/theme-kit'
|
|
1
|
+
import type { SlotCopy, ThreadViewModel } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
2
3
|
|
|
3
4
|
import { BUTTON, BUTTON_PRIMARY, HEADING, MICRO, NUMERIC, RULE } from '../shared'
|
|
4
5
|
|
|
5
6
|
const TAG = 'border px-1.5 py-px font-mono text-[0.625rem] font-bold uppercase tracking-[0.12em]'
|
|
6
7
|
|
|
7
|
-
export function ThreadView({
|
|
8
|
+
export function ThreadView({
|
|
9
|
+
thread,
|
|
10
|
+
forum,
|
|
11
|
+
replyHref,
|
|
12
|
+
markReadAction,
|
|
13
|
+
regions,
|
|
14
|
+
copy,
|
|
15
|
+
}: ThreadViewModel & { copy: SlotCopy }) {
|
|
16
|
+
const c = (key: string) => fromSlotCopy(copy, `raidframe.threadView.${key}`)
|
|
17
|
+
|
|
8
18
|
const reply =
|
|
9
19
|
replyHref === null ? null : (
|
|
10
20
|
<a href={replyHref} className={BUTTON_PRIMARY}>
|
|
11
|
-
|
|
21
|
+
{c('postReply')}
|
|
12
22
|
</a>
|
|
13
23
|
)
|
|
14
24
|
|
|
@@ -26,15 +36,19 @@ export function ThreadView({ thread, forum, replyHref, markReadAction, regions }
|
|
|
26
36
|
|
|
27
37
|
<p className="mt-1.5 flex flex-wrap items-center gap-2">
|
|
28
38
|
{thread.isSticky && (
|
|
29
|
-
<span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>
|
|
39
|
+
<span className={`${TAG} border-thread-pinned/60 text-thread-pinned`}>
|
|
40
|
+
{c('pinned')}
|
|
41
|
+
</span>
|
|
30
42
|
)}
|
|
31
43
|
{thread.isLocked && (
|
|
32
|
-
<span className={`${TAG} border-thread-locked/60 text-thread-locked`}>
|
|
44
|
+
<span className={`${TAG} border-thread-locked/60 text-thread-locked`}>
|
|
45
|
+
{c('locked')}
|
|
46
|
+
</span>
|
|
33
47
|
)}
|
|
34
48
|
<span className={`${MICRO} ${NUMERIC} normal-case`}>
|
|
35
|
-
<span className="text-foreground">{thread.replyCount}</span> replies
|
|
49
|
+
<span className="text-foreground">{thread.replyCount.label}</span> {c('replies')}
|
|
36
50
|
<span className="text-border">{' | '}</span>
|
|
37
|
-
<span className="text-foreground">{thread.viewCount}</span> views
|
|
51
|
+
<span className="text-foreground">{thread.viewCount.label}</span> {c('views')}
|
|
38
52
|
</span>
|
|
39
53
|
</p>
|
|
40
54
|
</div>
|
|
@@ -65,7 +79,7 @@ export function ThreadView({ thread, forum, replyHref, markReadAction, regions }
|
|
|
65
79
|
{markReadAction !== null && (
|
|
66
80
|
<form action={markReadAction} method="post">
|
|
67
81
|
<button type="submit" className={BUTTON}>
|
|
68
|
-
|
|
82
|
+
{c('markRead')}
|
|
69
83
|
</button>
|
|
70
84
|
</form>
|
|
71
85
|
)}
|
package/src/slots/user-panel.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { SlotCopy, UserPanelModel } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
1
3
|
import { Menu } from '@meith/ui/menu'
|
|
2
|
-
import type { UserPanelModel } from '@meith/theme-kit'
|
|
3
4
|
|
|
4
5
|
import { BUTTON, BUTTON_PRIMARY, MICRO } from '../shared'
|
|
5
6
|
|
|
@@ -30,7 +31,10 @@ export function UserPanel({
|
|
|
30
31
|
notificationsHref,
|
|
31
32
|
messagesHref,
|
|
32
33
|
children,
|
|
33
|
-
|
|
34
|
+
copy,
|
|
35
|
+
}: UserPanelModel & { copy: SlotCopy }) {
|
|
36
|
+
const c = (key: string) => fromSlotCopy(copy, `raidframe.userPanel.${key}`)
|
|
37
|
+
|
|
34
38
|
if (viewer.isGuest) {
|
|
35
39
|
return (
|
|
36
40
|
<div className="flex flex-wrap items-center gap-2">
|
|
@@ -43,7 +47,7 @@ export function UserPanel({
|
|
|
43
47
|
)
|
|
44
48
|
}
|
|
45
49
|
|
|
46
|
-
const name = viewer.username ?? '
|
|
50
|
+
const name = viewer.username ?? c('signedIn')
|
|
47
51
|
|
|
48
52
|
return (
|
|
49
53
|
<div className="flex flex-wrap items-center gap-2">
|
|
@@ -54,26 +58,26 @@ export function UserPanel({
|
|
|
54
58
|
}}
|
|
55
59
|
/>
|
|
56
60
|
|
|
57
|
-
{unreadNotifications > 0 && (
|
|
61
|
+
{unreadNotifications.value > 0 && (
|
|
58
62
|
<a
|
|
59
63
|
href={notificationsHref}
|
|
60
64
|
className={`${COUNT} border-primary/60 bg-primary/15 text-primary hover:border-primary`}
|
|
61
65
|
>
|
|
62
|
-
{unreadNotifications} new
|
|
66
|
+
{unreadNotifications.label} {c('new')}
|
|
63
67
|
</a>
|
|
64
68
|
)}
|
|
65
|
-
{unreadMessages > 0 && (
|
|
69
|
+
{unreadMessages.value > 0 && (
|
|
66
70
|
<a
|
|
67
71
|
href={messagesHref}
|
|
68
72
|
className={`${COUNT} border-forum-unread/60 bg-forum-unread/15 text-forum-unread hover:border-forum-unread`}
|
|
69
73
|
>
|
|
70
|
-
{unreadMessages} pm
|
|
74
|
+
{unreadMessages.label} {c('pm')}
|
|
71
75
|
</a>
|
|
72
76
|
)}
|
|
73
77
|
|
|
74
78
|
<div data-account="menu" className="flex min-w-0 items-center">
|
|
75
79
|
<Menu
|
|
76
|
-
label=
|
|
80
|
+
label={c('accountLabel')}
|
|
77
81
|
items={links}
|
|
78
82
|
triggerClassName="rounded-none border-border bg-card px-2 py-1 hover:border-primary/70 hover:bg-card"
|
|
79
83
|
trigger={
|
|
@@ -96,16 +100,12 @@ export function UserPanel({
|
|
|
96
100
|
<nav
|
|
97
101
|
data-account="plain"
|
|
98
102
|
style={{ display: 'none' }}
|
|
99
|
-
aria-label=
|
|
103
|
+
aria-label={c('accountLabel')}
|
|
100
104
|
className="flex-wrap items-center gap-x-3 gap-y-1"
|
|
101
105
|
>
|
|
102
106
|
<span className={`${MICRO} text-foreground`}>{name}</span>
|
|
103
107
|
{links.map((link) => (
|
|
104
|
-
<a
|
|
105
|
-
key={link.href}
|
|
106
|
-
href={link.href}
|
|
107
|
-
className={`${MICRO} hover:text-primary`}
|
|
108
|
-
>
|
|
108
|
+
<a key={link.href} href={link.href} className={`${MICRO} hover:text-primary`}>
|
|
109
109
|
{link.label}
|
|
110
110
|
</a>
|
|
111
111
|
))}
|
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import type { WhoIsOnlineModel } from '@meith/theme-kit'
|
|
1
|
+
import type { SlotCopy, WhoIsOnlineModel } from '@meith/theme-kit'
|
|
2
|
+
import { fromSlotCopy } from '@meith/theme-kit'
|
|
2
3
|
|
|
3
4
|
import { Frame, MICRO, NUMERIC, PanelHead, Stamp, UserRef } from '../shared'
|
|
4
5
|
|
|
5
6
|
export function WhoIsOnline({
|
|
6
7
|
guestCount,
|
|
7
8
|
members,
|
|
9
|
+
memberCount,
|
|
8
10
|
total,
|
|
9
11
|
recordCount,
|
|
10
12
|
recordAt,
|
|
11
13
|
fullListHref,
|
|
12
|
-
|
|
14
|
+
copy,
|
|
15
|
+
}: WhoIsOnlineModel & { copy: SlotCopy }) {
|
|
16
|
+
const c = (key: string) => fromSlotCopy(copy, `raidframe.whoIsOnline.${key}`)
|
|
17
|
+
|
|
13
18
|
return (
|
|
14
19
|
<Frame aria-labelledby="who-is-online-heading">
|
|
15
20
|
<PanelHead
|
|
16
21
|
id="who-is-online-heading"
|
|
17
|
-
title=
|
|
22
|
+
title={c('heading')}
|
|
18
23
|
aside={
|
|
19
24
|
<span className="inline-flex items-center gap-1.5 border border-moderation-approved/50 bg-moderation-approved/10 px-1.5 py-0.5">
|
|
20
25
|
<span
|
|
@@ -24,21 +29,21 @@ export function WhoIsOnline({
|
|
|
24
29
|
<span
|
|
25
30
|
className={`${NUMERIC} text-[0.625rem] font-bold tracking-[0.12em] text-moderation-approved uppercase`}
|
|
26
31
|
>
|
|
27
|
-
{total}
|
|
32
|
+
{total.label} {c('onlineSuffix')}
|
|
28
33
|
</span>
|
|
29
34
|
</span>
|
|
30
35
|
}
|
|
31
36
|
/>
|
|
32
37
|
|
|
33
38
|
<p className="px-3 py-2.5 text-xs">
|
|
34
|
-
{
|
|
35
|
-
<span className={MICRO}>
|
|
39
|
+
{memberCount.value === 0 ? (
|
|
40
|
+
<span className={MICRO}>{c('noMembers')}</span>
|
|
36
41
|
) : (
|
|
37
42
|
members.map((member, index) => (
|
|
38
43
|
<span key={member.username}>
|
|
39
44
|
{index > 0 && <span className="text-border">{' | '}</span>}
|
|
40
45
|
<UserRef user={member} className="text-foreground hover:text-primary" />
|
|
41
|
-
{member.isInvisible && <span className={`${MICRO} ml-1`}>hidden</span>}
|
|
46
|
+
{member.isInvisible && <span className={`${MICRO} ml-1`}>{c('hidden')}</span>}
|
|
42
47
|
</span>
|
|
43
48
|
))
|
|
44
49
|
)}
|
|
@@ -46,12 +51,16 @@ export function WhoIsOnline({
|
|
|
46
51
|
|
|
47
52
|
<p className={`${MICRO} border-t border-border px-3 py-1.5 normal-case`}>
|
|
48
53
|
<a href={fullListHref} className="uppercase hover:text-primary">
|
|
49
|
-
|
|
54
|
+
{c('fullList')}
|
|
50
55
|
</a>
|
|
51
56
|
<span className="text-border">{' | '}</span>
|
|
52
|
-
<span className="uppercase">
|
|
57
|
+
<span className="uppercase">
|
|
58
|
+
{guestCount.label} {c('guests')}
|
|
59
|
+
</span>
|
|
53
60
|
<span className="text-border">{' | '}</span>
|
|
54
|
-
<span className="uppercase">
|
|
61
|
+
<span className="uppercase">
|
|
62
|
+
{c('record')} {recordCount.label}
|
|
63
|
+
</span>
|
|
55
64
|
{recordAt !== null && (
|
|
56
65
|
<>
|
|
57
66
|
{' '}
|
package/src/theme.ts
CHANGED
|
@@ -1,6 +1,39 @@
|
|
|
1
1
|
import { defaultTheme } from '@meith/theme-default'
|
|
2
2
|
import { defineTheme } from '@meith/theme-kit'
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
announcementCopy,
|
|
6
|
+
authPageCopy,
|
|
7
|
+
boardIndexCopy,
|
|
8
|
+
boardStatsCopy,
|
|
9
|
+
categoryBlockCopy,
|
|
10
|
+
discoveryViewCopy,
|
|
11
|
+
errorNoticeCopy,
|
|
12
|
+
footerCopy,
|
|
13
|
+
forumDisplayCopy,
|
|
14
|
+
forumRowCopy,
|
|
15
|
+
headerCopy,
|
|
16
|
+
latestPostsCopy,
|
|
17
|
+
latestThreadsCopy,
|
|
18
|
+
memberProfileCopy,
|
|
19
|
+
navigationCopy,
|
|
20
|
+
noticeCopy,
|
|
21
|
+
paginationCopy,
|
|
22
|
+
panelNavCopy,
|
|
23
|
+
panelPageCopy,
|
|
24
|
+
postActionsCopy,
|
|
25
|
+
postBitCopy,
|
|
26
|
+
postFormCopy,
|
|
27
|
+
redirectNoticeCopy,
|
|
28
|
+
searchFormCopy,
|
|
29
|
+
searchResultsCopy,
|
|
30
|
+
shellCopy,
|
|
31
|
+
subforumListCopy,
|
|
32
|
+
threadRowCopy,
|
|
33
|
+
threadViewCopy,
|
|
34
|
+
userPanelCopy,
|
|
35
|
+
whoIsOnlineCopy,
|
|
36
|
+
} from './copy'
|
|
4
37
|
import { Announcement } from './slots/announcement'
|
|
5
38
|
import { AuthPage } from './slots/auth-page'
|
|
6
39
|
import { BoardIndex } from './slots/board-index'
|
|
@@ -81,4 +114,37 @@ export const raidframeTheme = defineTheme({
|
|
|
81
114
|
RedirectNotice,
|
|
82
115
|
ErrorNotice,
|
|
83
116
|
},
|
|
117
|
+
copy: {
|
|
118
|
+
Announcement: announcementCopy,
|
|
119
|
+
AuthPage: authPageCopy,
|
|
120
|
+
BoardIndex: boardIndexCopy,
|
|
121
|
+
BoardStats: boardStatsCopy,
|
|
122
|
+
CategoryBlock: categoryBlockCopy,
|
|
123
|
+
DiscoveryView: discoveryViewCopy,
|
|
124
|
+
ErrorNotice: errorNoticeCopy,
|
|
125
|
+
Footer: footerCopy,
|
|
126
|
+
ForumDisplay: forumDisplayCopy,
|
|
127
|
+
ForumRow: forumRowCopy,
|
|
128
|
+
Header: headerCopy,
|
|
129
|
+
LatestPosts: latestPostsCopy,
|
|
130
|
+
LatestThreads: latestThreadsCopy,
|
|
131
|
+
MemberProfile: memberProfileCopy,
|
|
132
|
+
Navigation: navigationCopy,
|
|
133
|
+
Notice: noticeCopy,
|
|
134
|
+
Pagination: paginationCopy,
|
|
135
|
+
PanelNav: panelNavCopy,
|
|
136
|
+
PanelPage: panelPageCopy,
|
|
137
|
+
PostActions: postActionsCopy,
|
|
138
|
+
PostBit: postBitCopy,
|
|
139
|
+
PostForm: postFormCopy,
|
|
140
|
+
RedirectNotice: redirectNoticeCopy,
|
|
141
|
+
SearchForm: searchFormCopy,
|
|
142
|
+
SearchResults: searchResultsCopy,
|
|
143
|
+
Shell: shellCopy,
|
|
144
|
+
SubforumList: subforumListCopy,
|
|
145
|
+
ThreadRow: threadRowCopy,
|
|
146
|
+
ThreadView: threadViewCopy,
|
|
147
|
+
UserPanel: userPanelCopy,
|
|
148
|
+
WhoIsOnline: whoIsOnlineCopy,
|
|
149
|
+
},
|
|
84
150
|
})
|