summaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/a-h/templ/once.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/a-h/templ/once.go')
-rw-r--r--vendor/github.com/a-h/templ/once.go64
1 files changed, 64 insertions, 0 deletions
diff --git a/vendor/github.com/a-h/templ/once.go b/vendor/github.com/a-h/templ/once.go
new file mode 100644
index 0000000..7860ab8
--- /dev/null
+++ b/vendor/github.com/a-h/templ/once.go
@@ -0,0 +1,64 @@
+package templ
+
+import (
+ "context"
+ "io"
+ "sync/atomic"
+)
+
+// onceHandleIndex is used to identify unique once handles in a program run.
+var onceHandleIndex int64
+
+type OnceOpt func(*OnceHandle)
+
+// WithOnceComponent sets the component to be rendered once per context.
+// This can be used instead of setting the children of the `Once` method,
+// for example, if creating a code component outside of a templ HTML template.
+func WithComponent(c Component) OnceOpt {
+ return func(o *OnceHandle) {
+ o.c = c
+ }
+}
+
+// NewOnceHandle creates a OnceHandle used to ensure that the children of its
+// `Once` method are only rendered once per context.
+func NewOnceHandle(opts ...OnceOpt) *OnceHandle {
+ oh := &OnceHandle{
+ id: atomic.AddInt64(&onceHandleIndex, 1),
+ }
+ for _, opt := range opts {
+ opt(oh)
+ }
+ return oh
+}
+
+// OnceHandle is used to ensure that the children of its `Once` method are are only
+// rendered once per context.
+type OnceHandle struct {
+ // id is used to identify which instance of the OnceHandle is being used.
+ // The OnceHandle can't be an empty struct, because:
+ //
+ // | Two distinct zero-size variables may
+ // | have the same address in memory
+ //
+ // https://go.dev/ref/spec#Size_and_alignment_guarantees
+ id int64
+ // c is the component to be rendered once per context.
+ // if c is nil, the children of the `Once` method are rendered.
+ c Component
+}
+
+// Once returns a component that renders its children once per context.
+func (o *OnceHandle) Once() Component {
+ return ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
+ _, v := getContext(ctx)
+ if v.getHasBeenRendered(o) {
+ return nil
+ }
+ v.setHasBeenRendered(o)
+ if o.c != nil {
+ return o.c.Render(ctx, w)
+ }
+ return GetChildren(ctx).Render(ctx, w)
+ })
+}